diff --git a/be/src/core/call_on_type_index.h b/be/src/core/call_on_type_index.h index 98aad077413a56..7056abb6d721ce 100644 --- a/be/src/core/call_on_type_index.h +++ b/be/src/core/call_on_type_index.h @@ -37,6 +37,7 @@ struct TypePair { class DataTypeDate; class DataTypeDateV2; class DataTypeDateTimeV2; +class DataTypeTimeStampNs; class DataTypeDateTime; class DataTypeIPv4; class DataTypeIPv6; @@ -83,6 +84,8 @@ bool call_on_index_and_data_type(PrimitiveType number, F&& f) { return f(TypePair()); case PrimitiveType::TYPE_DATETIMEV2: return f(TypePair()); + case PrimitiveType::TYPE_TIMESTAMP_NS: + return f(TypePair()); case PrimitiveType::TYPE_DATETIME: return f(TypePair()); case PrimitiveType::TYPE_TIMEV2: @@ -236,6 +239,8 @@ bool dispatch_type_base(PrimitiveType number, F&& f) { return f(DispatchDataType()); case PrimitiveType::TYPE_DATETIMEV2: return f(DispatchDataType()); + case PrimitiveType::TYPE_TIMESTAMP_NS: + return f(DispatchDataType()); case PrimitiveType::TYPE_DATETIME: return f(DispatchDataType()); case PrimitiveType::TYPE_TIMEV2: diff --git a/be/src/core/column/column_array.cpp b/be/src/core/column/column_array.cpp index 604c46948539b1..dad91af31c01cf 100644 --- a/be/src/core/column/column_array.cpp +++ b/be/src/core/column/column_array.cpp @@ -874,6 +874,9 @@ ColumnArrayDataOffsets filter_return_new_dispatch(const Filter& filt, ssize_t re return filter_number_return_new(filt, result_size_hint, data, offsets); if (check_and_get_column(data.get())) return filter_number_return_new(filt, result_size_hint, data, offsets); + if (check_and_get_column(data.get())) { + return filter_number_return_new(filt, result_size_hint, data, offsets); + } if (check_and_get_column(data.get())) return filter_number_return_new(filt, result_size_hint, data, offsets); if (check_and_get_column(data.get())) @@ -940,6 +943,9 @@ size_t filter_inplace_dispatch(const Filter& filter, IColumn& src_data, return filter_number_inplace(filter, src_data, src_offsets); if (check_and_get_column(&src_data)) return filter_number_inplace(filter, src_data, src_offsets); + if (check_and_get_column(&src_data)) { + return filter_number_inplace(filter, src_data, src_offsets); + } if (check_and_get_column(&src_data)) return filter_number_inplace(filter, src_data, src_offsets); if (check_and_get_column(&src_data)) diff --git a/be/src/core/column/column_array.h b/be/src/core/column/column_array.h index 645b1662d7b238..dc810e8b800f35 100644 --- a/be/src/core/column/column_array.h +++ b/be/src/core/column/column_array.h @@ -46,7 +46,7 @@ class SipHash; ColumnFloat64, ColumnDecimal32, ColumnDecimal64, ColumnDecimal128V3, \ ColumnDecimal128V2, ColumnDecimal256 #define ALL_COLUMNS_TIME \ - ColumnDate, ColumnDateTime, ColumnDateV2, ColumnDateTimeV2, ColumnTimeStampTz + ColumnDate, ColumnDateTime, ColumnDateV2, ColumnDateTimeV2, ColumnTimeStampNs, ColumnTimeStampTz #define ALL_COLUMNS_NUMERIC ALL_COLUMNS_NUMBER, ALL_COLUMNS_TIME #define ALL_COLUMNS_SIMPLE ALL_COLUMNS_NUMERIC, ColumnString, ColumnIPv4, ColumnIPv6 diff --git a/be/src/core/column/column_vector.cpp b/be/src/core/column/column_vector.cpp index 31e4862187fb79..8d43364e5a898d 100644 --- a/be/src/core/column/column_vector.cpp +++ b/be/src/core/column/column_vector.cpp @@ -559,6 +559,7 @@ template class ColumnVector; template class ColumnVector; template class ColumnVector; template class ColumnVector; +template class ColumnVector; template class ColumnVector; template class ColumnVector; template class ColumnVector; diff --git a/be/src/core/column/column_vector.h b/be/src/core/column/column_vector.h index 4f3a7a6c46f2b4..6c55fa679fd0d7 100644 --- a/be/src/core/column/column_vector.h +++ b/be/src/core/column/column_vector.h @@ -70,7 +70,7 @@ template class ColumnVector final : public COWHelper> { static_assert(is_int_or_bool(T) || is_ip(T) || is_date_type(T) || is_float_or_double(T) || T == TYPE_TIMEV2 || T == TYPE_UINT32 || T == TYPE_UINT64 || - T == TYPE_TIMESTAMPTZ); + T == TYPE_TIMESTAMPTZ || is_timestamp_ns_type(T)); private: using Self = ColumnVector; @@ -120,7 +120,7 @@ class ColumnVector final : public COWHelper> { void insert_range_of_integer(value_type begin, value_type end) { if constexpr (!is_float_or_double(T) && T != TYPE_TIMEV2 && T != TYPE_TIMESTAMPTZ && - !is_date_type(T)) { + !is_date_type(T) && !is_timestamp_ns_type(T)) { auto old_size = data.size(); auto new_size = old_size + static_cast(end - begin); data.resize(new_size); @@ -321,7 +321,7 @@ class ColumnVector final : public COWHelper> { } Int64 get_int(size_t n) const override { - if constexpr (is_date_type(T) || T == TYPE_TIMESTAMPTZ) { + if constexpr (is_date_type(T) || T == TYPE_TIMESTAMPTZ || is_timestamp_ns_type(T)) { throw doris::Exception(ErrorCode::NOT_IMPLEMENTED_ERROR, "Method get_int is not supported for " + get_name()); return 0; @@ -437,6 +437,7 @@ using ColumnDate = ColumnVector; using ColumnDateTime = ColumnVector; using ColumnDateV2 = ColumnVector; using ColumnDateTimeV2 = ColumnVector; +using ColumnTimeStampNs = ColumnVector; using ColumnFloat32 = ColumnVector; using ColumnFloat64 = ColumnVector; using ColumnIPv4 = ColumnVector; diff --git a/be/src/core/column/columns_common.cpp b/be/src/core/column/columns_common.cpp index bfaee36a8e0058..1129032dc07c11 100644 --- a/be/src/core/column/columns_common.cpp +++ b/be/src/core/column/columns_common.cpp @@ -359,6 +359,8 @@ INSTANTIATE(DateV2Value, IColumn::Offset) INSTANTIATE(DateV2Value, ColumnArray::Offset64) INSTANTIATE(DateV2Value, IColumn::Offset) INSTANTIATE(DateV2Value, ColumnArray::Offset64) +INSTANTIATE(TimeStampNsValue, IColumn::Offset) +INSTANTIATE(TimeStampNsValue, ColumnArray::Offset64) INSTANTIATE(TimestampTzValue, IColumn::Offset) INSTANTIATE(TimestampTzValue, ColumnArray::Offset64) INSTANTIATE(UInt32, IColumn::Offset) diff --git a/be/src/core/column/variant_v2/column_variant_v2_typed_column.cpp b/be/src/core/column/variant_v2/column_variant_v2_typed_column.cpp index 85fe0be04314a6..1fcf0b1d8d92f1 100644 --- a/be/src/core/column/variant_v2/column_variant_v2_typed_column.cpp +++ b/be/src/core/column/variant_v2/column_variant_v2_typed_column.cpp @@ -37,6 +37,7 @@ bool is_supported_variant_typed_identity(PrimitiveType type) { case TYPE_DATEV2: case TYPE_DATETIME: case TYPE_DATETIMEV2: + case TYPE_TIMESTAMP_NS: case TYPE_TIMESTAMPTZ: case TYPE_CHAR: case TYPE_VARCHAR: diff --git a/be/src/core/column/variant_v2/column_variant_v2_typed_column.h b/be/src/core/column/variant_v2/column_variant_v2_typed_column.h index f5aca49a746dc5..a37057a00be668 100644 --- a/be/src/core/column/variant_v2/column_variant_v2_typed_column.h +++ b/be/src/core/column/variant_v2/column_variant_v2_typed_column.h @@ -117,6 +117,8 @@ void with_variant_typed_scalar(const Column& column, size_t row, uint8_t scale, } else if constexpr (Type == TYPE_DATETIMEV2) { const int64_t value = variant_timestamp_micros(column.get_data()[row], row, "DATETIMEV2"); callback(VariantScalarRef::timestamp_micros(value, false)); + } else if constexpr (Type == TYPE_TIMESTAMP_NS) { + callback(VariantScalarRef::timestamp_nanos(column.get_data()[row].epoch_nanos(), false)); } else if constexpr (Type == TYPE_TIMESTAMPTZ) { const int64_t value = variant_timestamp_micros(column.get_data()[row], row, "TIMESTAMPTZ"); callback(VariantScalarRef::timestamp_micros(value, true)); diff --git a/be/src/core/data_type/convert_field_to_type.cpp b/be/src/core/data_type/convert_field_to_type.cpp index 4e5938210ac492..d4f0564d2b7c10 100644 --- a/be/src/core/data_type/convert_field_to_type.cpp +++ b/be/src/core/data_type/convert_field_to_type.cpp @@ -58,6 +58,9 @@ void dispatch(F&& f, const Field& field) { case PrimitiveType::TYPE_DATETIMEV2: f(field.template get()); return; + case PrimitiveType::TYPE_TIMESTAMP_NS: + f(field.template get()); + return; case PrimitiveType::TYPE_TIMESTAMPTZ: f(field.template get()); return; @@ -180,6 +183,9 @@ class FieldVisitorToJsonb : public StaticVisitor { void operator()(const DateV2Value& x, JsonbWriter* writer) const { writer->writeInt64(*(UInt64*)&x); } + void operator()(const TimeStampNsValue& x, JsonbWriter* writer) const { + writer->writeInt64(x.epoch_nanos()); + } void operator()(const TimestampTzValue& x, JsonbWriter* writer) const { writer->writeInt64(*(UInt64*)&x); } diff --git a/be/src/core/data_type/data_type.cpp b/be/src/core/data_type/data_type.cpp index 941a0377b05e66..d5980d4a8ecd80 100644 --- a/be/src/core/data_type/data_type.cpp +++ b/be/src/core/data_type/data_type.cpp @@ -126,6 +126,8 @@ PGenericType_TypeId IDataType::get_pdata_type(const IDataType* data_type) { return PGenericType::VARIANT; case PrimitiveType::TYPE_DATETIMEV2: return PGenericType::DATETIMEV2; + case PrimitiveType::TYPE_TIMESTAMP_NS: + return PGenericType::TIMESTAMP_NS; case PrimitiveType::TYPE_TIMESTAMPTZ: return PGenericType::TIMESTAMPTZ; case PrimitiveType::TYPE_BITMAP: diff --git a/be/src/core/data_type/data_type_factory.cpp b/be/src/core/data_type/data_type_factory.cpp index 92e32f4d6459bb..d86478a62ea183 100644 --- a/be/src/core/data_type/data_type_factory.cpp +++ b/be/src/core/data_type/data_type_factory.cpp @@ -59,6 +59,7 @@ #include "core/data_type/data_type_string.h" #include "core/data_type/data_type_struct.h" #include "core/data_type/data_type_time.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/data_type/data_type_timestamptz.h" #include "core/data_type/data_type_varbinary.h" #include "core/data_type/data_type_variant.h" @@ -157,6 +158,9 @@ DataTypePtr DataTypeFactory::_create_primitive_data_type(const FieldType& type, case FieldType::OLAP_FIELD_TYPE_DATETIMEV2: result = create_datetimev2(scale); break; + case FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS: + result = std::make_shared(); + break; case FieldType::OLAP_FIELD_TYPE_TIMESTAMPTZ: result = std::make_shared(scale); break; @@ -263,6 +267,9 @@ DataTypePtr DataTypeFactory::create_data_type(const PColumnMeta& pcolumn) { case PGenericType::DATETIMEV2: nested = std::make_shared(pcolumn.decimal_param().scale()); break; + case PGenericType::TIMESTAMP_NS: + nested = std::make_shared(); + break; case PGenericType::DATETIME: nested = std::make_shared(); break; @@ -441,6 +448,9 @@ DataTypePtr DataTypeFactory::create_data_type(const PrimitiveType primitive_type case TYPE_DATETIMEV2: nested = create_datetimev2(scale); break; + case TYPE_TIMESTAMP_NS: + nested = std::make_shared(); + break; case TYPE_DATETIME: nested = std::make_shared(); break; diff --git a/be/src/core/data_type/data_type_number_base.cpp b/be/src/core/data_type/data_type_number_base.cpp index dcd167bce1df0d..4dccbb9c75cc37 100644 --- a/be/src/core/data_type/data_type_number_base.cpp +++ b/be/src/core/data_type/data_type_number_base.cpp @@ -62,7 +62,7 @@ std::string DataTypeNumberBase::to_string( return std::to_string(value); } else if constexpr (T == TYPE_DATETIME || T == TYPE_DATE) { return std::to_string(binary_cast(value)); - } else if constexpr (is_date_type(T) || T == TYPE_TIMESTAMPTZ) { + } else if constexpr (is_date_type(T) || T == TYPE_TIMESTAMPTZ || is_timestamp_ns_type(T)) { return std::to_string(value.to_date_int_val()); } else if constexpr (std::numeric_limits::CppType>::is_iec559) { return CastToString::from_number(value); @@ -186,8 +186,12 @@ FieldWithDataType DataTypeNumberBase::get_field_with_data_type(const IColumn& assert_cast&, TypeCheckOnRelease::DISABLE>(column); Field field; column_data.get(row_num, field); - return FieldWithDataType {.field = std::move(field), - .base_scalar_type_id = get_primitive_type()}; + auto field_with_data_type = FieldWithDataType {.field = std::move(field), + .base_scalar_type_id = get_primitive_type()}; + if constexpr (T == TYPE_TIMESTAMP_NS) { + field_with_data_type.scale = static_cast(get_scale()); + } + return field_with_data_type; } /// Explicit template instantiations - to avoid code bloat in headers. @@ -203,6 +207,7 @@ template class DataTypeNumberBase; template class DataTypeNumberBase; template class DataTypeNumberBase; template class DataTypeNumberBase; +template class DataTypeNumberBase; template class DataTypeNumberBase; template class DataTypeNumberBase; template class DataTypeNumberBase; diff --git a/be/src/core/data_type/data_type_number_base.h b/be/src/core/data_type/data_type_number_base.h index f3fe2544196fce..930de55bb0eb4b 100644 --- a/be/src/core/data_type/data_type_number_base.h +++ b/be/src/core/data_type/data_type_number_base.h @@ -48,7 +48,7 @@ class IColumn; template class DataTypeNumberBase : public IDataType { static_assert(is_int_or_bool(T) || is_ip(T) || is_date_type(T) || is_float_or_double(T) || - T == TYPE_TIMEV2 || T == TYPE_TIMESTAMPTZ); + T == TYPE_TIMEV2 || T == TYPE_TIMESTAMPTZ || is_timestamp_ns_type(T)); public: static constexpr bool is_parametric = false; diff --git a/be/src/core/data_type/data_type_time.h b/be/src/core/data_type/data_type_time.h index afcc97fe8e1853..1a0e083a4ee1c2 100644 --- a/be/src/core/data_type/data_type_time.h +++ b/be/src/core/data_type/data_type_time.h @@ -40,8 +40,10 @@ class IColumn; class DataTypeTimeV2 final : public DataTypeNumberBase { public: + static constexpr UInt32 MAX_SCALE = 6; + DataTypeTimeV2(int scale = 0) : _scale(scale) { - if (UNLIKELY(scale > 6)) { + if (UNLIKELY(scale > static_cast(MAX_SCALE))) { throw doris::Exception(ErrorCode::INTERNAL_ERROR, "Scale {} is out of bounds", scale); } if (scale == -1) { diff --git a/be/src/core/data_type/data_type_timestamp_ns.cpp b/be/src/core/data_type/data_type_timestamp_ns.cpp new file mode 100644 index 00000000000000..fb2527a9997185 --- /dev/null +++ b/be/src/core/data_type/data_type_timestamp_ns.cpp @@ -0,0 +1,44 @@ +// 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 "core/data_type/data_type_timestamp_ns.h" + +#include +#include + +#include "common/exception.h" +#include "core/string_ref.h" + +namespace doris { + +Field DataTypeTimeStampNs::get_field(const TExprNode& node) const { + int64_t value = 0; + const StringRef string_value(node.date_literal.value.data(), node.date_literal.value.size()); + const auto status = parse_timestamp_ns(string_value, &value); + if (!status.ok()) { + throw doris::Exception(doris::ErrorCode::INVALID_ARGUMENT, + "Invalid value: {} for type TimeStampNs: {}", + node.date_literal.value, status.to_string()); + } + return Field::create_field(TimeStampNsValue(value)); +} + +bool DataTypeTimeStampNs::equals(const IDataType& rhs) const { + return typeid(rhs) == typeid(*this); +} + +} // namespace doris diff --git a/be/src/core/data_type/data_type_timestamp_ns.h b/be/src/core/data_type/data_type_timestamp_ns.h new file mode 100644 index 00000000000000..81eeb98705794d --- /dev/null +++ b/be/src/core/data_type/data_type_timestamp_ns.h @@ -0,0 +1,44 @@ +// 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. + +#pragma once + +#include +#include + +#include "core/data_type/data_type_number_base.h" +#include "core/data_type_serde/data_type_timestamp_ns_serde.h" +#include "core/value/timestamp_ns_value.h" + +namespace doris { + +class DataTypeTimeStampNs final : public DataTypeNumberBase { +public: + const std::string get_family_name() const override { return "TimeStampNs"; } + + bool equals(const IDataType& rhs) const override; + + using SerDeType = DataTypeTimeStampNsSerDe; + DataTypeSerDeSPtr get_serde(int nesting_level = 1) const override { + return std::make_shared(nesting_level); + } + + Field get_field(const TExprNode& node) const override; + UInt32 get_scale() const override { return TimeStampNsValue::FRACTIONAL_DIGITS; } +}; + +} // namespace doris diff --git a/be/src/core/data_type/define_primitive_type.h b/be/src/core/data_type/define_primitive_type.h index 852b68a96b5358..6606242cf1d257 100644 --- a/be/src/core/data_type/define_primitive_type.h +++ b/be/src/core/data_type/define_primitive_type.h @@ -73,7 +73,8 @@ enum PrimitiveType : PrimitiveNative { TYPE_UINT64, /* 39, used as offset */ TYPE_FIXED_LENGTH_OBJECT, /* 40, represent fixed-length object on BE */ TYPE_VARBINARY, /* 41, varbinary */ - TYPE_TIMESTAMPTZ /* 42, timestamptz */ + TYPE_TIMESTAMPTZ, /* 42, timestamptz */ + TYPE_TIMESTAMP_NS /* 43, signed Int64 epoch nanoseconds */ }; } // namespace doris diff --git a/be/src/core/data_type/primitive_type.cpp b/be/src/core/data_type/primitive_type.cpp index 746fc655323a22..208e9e9f411caa 100644 --- a/be/src/core/data_type/primitive_type.cpp +++ b/be/src/core/data_type/primitive_type.cpp @@ -69,6 +69,9 @@ PrimitiveType thrift_to_type(TPrimitiveType::type ttype) { case TPrimitiveType::DATETIMEV2: return TYPE_DATETIMEV2; + case TPrimitiveType::TIMESTAMP_NS: + return TYPE_TIMESTAMP_NS; + case TPrimitiveType::TIMEV2: return TYPE_TIMEV2; @@ -191,6 +194,9 @@ TPrimitiveType::type to_thrift(PrimitiveType ptype) { case TYPE_DATETIMEV2: return TPrimitiveType::DATETIMEV2; + case TYPE_TIMESTAMP_NS: + return TPrimitiveType::TIMESTAMP_NS; + case TYPE_TIMEV2: return TPrimitiveType::TIMEV2; @@ -305,6 +311,9 @@ std::string type_to_string(PrimitiveType t) { case TYPE_DATETIMEV2: return "DATETIMEV2"; + case TYPE_TIMESTAMP_NS: + return "TIMESTAMP_NS"; + case TYPE_TIMEV2: return "TIMEV2"; diff --git a/be/src/core/data_type/primitive_type.h b/be/src/core/data_type/primitive_type.h index c236c2111d1f8b..0e11c783a252ed 100644 --- a/be/src/core/data_type/primitive_type.h +++ b/be/src/core/data_type/primitive_type.h @@ -31,6 +31,7 @@ #include "core/string_view.h" #include "core/types.h" #include "core/uint24.h" +#include "core/value/timestamp_ns_value.h" #include "core/value/timestamptz_value.h" #include "core/value/vdatetime_value.h" #include "exec/common/template_helpers.hpp" @@ -73,6 +74,7 @@ class DataTypeTimeV2; class DataTypeDateTime; class DataTypeDate; class DataTypeDateTimeV2; +class DataTypeTimeStampNs; class DataTypeDateV2; class DataTypeTimeStampTz; template @@ -110,6 +112,7 @@ using ColumnDateTime = ColumnVector; using ColumnDateV2 = ColumnVector; using ColumnTimeStampTz = ColumnVector; using ColumnDateTimeV2 = ColumnVector; +using ColumnTimeStampNs = ColumnVector; using ColumnFloat32 = ColumnVector; using ColumnFloat64 = ColumnVector; using ColumnIPv4 = ColumnVector; @@ -138,6 +141,7 @@ constexpr bool is_enumeration_type(PrimitiveType type) { case TYPE_STRING: case TYPE_DATETIME: case TYPE_DATETIMEV2: + case TYPE_TIMESTAMP_NS: case TYPE_TIMESTAMPTZ: case TYPE_TIMEV2: case TYPE_DECIMALV2: @@ -176,6 +180,10 @@ constexpr bool is_date_type(PrimitiveType type) { type == TYPE_DATEV2; } +constexpr bool is_timestamp_ns_type(PrimitiveType type) { + return type == TYPE_TIMESTAMP_NS; +} + constexpr bool is_time_type(PrimitiveType type) { return type == TYPE_TIMEV2; } @@ -364,6 +372,13 @@ struct PrimitiveTypeTraits { using ColumnType = ColumnDateTimeV2; }; template <> +struct PrimitiveTypeTraits { + using CppType = TimeStampNsValue; + using StorageFieldType = int64_t; + using DataType = DataTypeTimeStampNs; + using ColumnType = ColumnTimeStampNs; +}; +template <> struct PrimitiveTypeTraits { using CppType = DateV2Value; using StorageFieldType = uint32_t; diff --git a/be/src/core/data_type/storage_field_type.cpp b/be/src/core/data_type/storage_field_type.cpp index 269015401dcab7..ec10e25ee68e8a 100644 --- a/be/src/core/data_type/storage_field_type.cpp +++ b/be/src/core/data_type/storage_field_type.cpp @@ -73,6 +73,8 @@ FieldType primitive_type_to_storage_field_type(PrimitiveType type) { return FieldType::OLAP_FIELD_TYPE_DATEV2; case PrimitiveType::TYPE_DATETIMEV2: return FieldType::OLAP_FIELD_TYPE_DATETIMEV2; + case PrimitiveType::TYPE_TIMESTAMP_NS: + return FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS; case PrimitiveType::TYPE_TIMEV2: return FieldType::OLAP_FIELD_TYPE_TIMEV2; case PrimitiveType::TYPE_DECIMAL32: @@ -167,6 +169,8 @@ PrimitiveType storage_field_type_to_primitive_type(FieldType type) { return PrimitiveType::TYPE_DATEV2; case FieldType::OLAP_FIELD_TYPE_DATETIMEV2: return PrimitiveType::TYPE_DATETIMEV2; + case FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS: + return PrimitiveType::TYPE_TIMESTAMP_NS; case FieldType::OLAP_FIELD_TYPE_TIMEV2: return PrimitiveType::TYPE_TIMEV2; case FieldType::OLAP_FIELD_TYPE_DECIMAL32: diff --git a/be/src/core/data_type_serde/data_type_number_serde.cpp b/be/src/core/data_type_serde/data_type_number_serde.cpp index 857d8eacc91682..cd021f649cb362 100644 --- a/be/src/core/data_type_serde/data_type_number_serde.cpp +++ b/be/src/core/data_type_serde/data_type_number_serde.cpp @@ -737,6 +737,13 @@ Status DataTypeNumberSerDe::write_column_to_arrow(const IColumn& column, cons return Status::OK(); } +template <> +Status DataTypeNumberSerDe::write_column_to_arrow( + const IColumn& column, const NullMap* null_map, arrow::ArrayBuilder* array_builder, + int64_t start, int64_t end, const cctz::time_zone& ctz) const { + return Status::NotSupported("DataTypeNumberSerDe::write_column_to_arrow"); +} + template Status DataTypeNumberSerDe::read_column_from_decoded_values( IColumn& column, const DecodedColumnView& view) const { @@ -1117,8 +1124,8 @@ template constexpr bool can_write_to_jsonb_from_number() { return T == TYPE_BOOLEAN || T == TYPE_TINYINT || T == TYPE_SMALLINT || T == TYPE_INT || T == TYPE_BIGINT || T == TYPE_LARGEINT || T == TYPE_FLOAT || T == TYPE_DOUBLE || - T == TYPE_DATEV2 || T == TYPE_DATETIMEV2 || T == TYPE_TIMESTAMPTZ || T == TYPE_IPV4 || - T == TYPE_IPV6 || T == TYPE_TIMEV2; + T == TYPE_DATEV2 || T == TYPE_DATETIMEV2 || T == TYPE_TIMESTAMP_NS || + T == TYPE_TIMESTAMPTZ || T == TYPE_IPV4 || T == TYPE_IPV6 || T == TYPE_TIMEV2; } template @@ -1156,6 +1163,8 @@ bool write_to_jsonb_from_number(auto& data, JsonbWriter& writer, int scale) { return jsonb_writer_string(writer, CastToString::from_datev2(data)); } else if constexpr (T == TYPE_DATETIMEV2) { return jsonb_writer_string(writer, CastToString::from_datetimev2(data, scale)); + } else if constexpr (T == TYPE_TIMESTAMP_NS) { + return jsonb_writer_string(writer, TimeStampNsValue(data).to_string()); } else if constexpr (T == TYPE_TIMESTAMPTZ) { return jsonb_writer_string(writer, CastToString::from_timestamptz(data, scale)); } else if constexpr (T == TYPE_IPV4) { @@ -1445,6 +1454,8 @@ void DataTypeNumberSerDe::read_one_cell_from_jsonb(IColumn& column, col.insert_value(binary_cast(static_cast(read_int()))); } else if constexpr (T == TYPE_BIGINT) { col.insert_value(static_cast(read_int())); + } else if constexpr (T == TYPE_TIMESTAMP_NS) { + col.insert_value(TimeStampNsValue(static_cast(read_int()))); } else if constexpr (T == TYPE_LARGEINT) { col.insert_value(static_cast<__int128_t>(read_int())); } else if constexpr (T == TYPE_FLOAT) { @@ -1489,7 +1500,7 @@ void DataTypeNumberSerDe::write_one_cell_to_jsonb(const IColumn& column, int32_t val = *reinterpret_cast(data_ref.data); result.writeInt32(val); } else if constexpr (T == TYPE_BIGINT || T == TYPE_DATE || T == TYPE_DATETIME || - T == TYPE_DATETIMEV2 || T == TYPE_TIMESTAMPTZ) { + T == TYPE_DATETIMEV2 || T == TYPE_TIMESTAMP_NS || T == TYPE_TIMESTAMPTZ) { int64_t val = *reinterpret_cast(data_ref.data); if (options.enable_row_store_compact_jsonb) { result.writeInt(val); @@ -1751,6 +1762,10 @@ const uint8_t* DataTypeNumberSerDe::deserialize_binary_to_column(const uint8_ col.insert_value(binary_cast>( unaligned_load(data))); data += sizeof(UInt64); + } else if constexpr (T == TYPE_TIMESTAMP_NS) { + data += sizeof(uint8_t); + col.insert_value(TimeStampNsValue(unaligned_load(data))); + data += sizeof(Int64); } else { throw doris::Exception(ErrorCode::NOT_IMPLEMENTED_ERROR, "deserialize_binary_to_column with type '{}'", type_to_string(T)); @@ -1817,6 +1832,14 @@ const uint8_t* DataTypeNumberSerDe::deserialize_binary_to_field(const uint8_t info.scale = static_cast(scale); field = Field::create_field(*(typename PrimitiveTypeTraits::CppType*)&v); data += sizeof(UInt64); + } else if constexpr (T == TYPE_TIMESTAMP_NS) { + const uint8_t scale = *data; + data += sizeof(uint8_t); + info.precision = -1; + info.scale = static_cast(scale); + field = Field::create_field( + TimeStampNsValue(unaligned_load(data))); + data += sizeof(Int64); } else { throw doris::Exception(ErrorCode::NOT_IMPLEMENTED_ERROR, "deserialize_binary_to_column with type '{}'", type_to_string(T)); @@ -1835,6 +1858,9 @@ void value_to_string(const typename PrimitiveTypeTraits::CppType value, Buffe CastToString::push_datev2(value, bw); } else if constexpr (T == TYPE_DATETIMEV2) { CastToString::push_datetimev2(value, scale, bw); + } else if constexpr (T == TYPE_TIMESTAMP_NS) { + const auto string_value = TimeStampNsValue(value).to_string(); + bw.write(string_value.data(), string_value.size()); } else if constexpr (T == TYPE_TIMESTAMPTZ) { CastToString::push_timestamptz(value, scale, bw, options); } else if constexpr (T == TYPE_TIMEV2) { @@ -1851,7 +1877,8 @@ template void DataTypeNumberSerDe::to_string(const IColumn& column, size_t row_num, BufferWritable& bw, const FormatOptions& options) const { auto& data = assert_cast(column).get_data(); - if constexpr (is_timestamptz_type(T) || is_date_type(T) || is_time_type(T) || is_ip(T)) { + if constexpr (is_timestamptz_type(T) || is_date_type(T) || is_timestamp_ns_type(T) || + is_time_type(T) || is_ip(T)) { if (_nesting_level > 1) { bw.write('"'); } @@ -1878,7 +1905,8 @@ bool DataTypeNumberSerDe::write_column_to_hive_text(const IColumn& column, Bu int64_t row_idx, const FormatOptions& options) const { auto& data = assert_cast(column).get_data(); - if constexpr (is_date_type(T) || is_timestamptz_type(T) || is_time_type(T) || is_ip(T)) { + if constexpr (is_date_type(T) || is_timestamptz_type(T) || is_timestamp_ns_type(T) || + is_time_type(T) || is_ip(T)) { if (_nesting_level > 1) { bw.write('"'); } @@ -1961,6 +1989,7 @@ template class DataTypeNumberSerDe; template class DataTypeNumberSerDe; template class DataTypeNumberSerDe; template class DataTypeNumberSerDe; +template class DataTypeNumberSerDe; template class DataTypeNumberSerDe; template class DataTypeNumberSerDe; template class DataTypeNumberSerDe; diff --git a/be/src/core/data_type_serde/data_type_number_serde.h b/be/src/core/data_type_serde/data_type_number_serde.h index 9c0de8cb0c0e8a..762802852e198e 100644 --- a/be/src/core/data_type_serde/data_type_number_serde.h +++ b/be/src/core/data_type_serde/data_type_number_serde.h @@ -49,7 +49,7 @@ class Arena; template class DataTypeNumberSerDe : public DataTypeSerDe { static_assert(is_int_or_bool(T) || is_ip(T) || is_date_type(T) || is_float_or_double(T) || - T == TYPE_TIMEV2 || T == TYPE_TIMESTAMPTZ); + T == TYPE_TIMEV2 || T == TYPE_TIMESTAMPTZ || is_timestamp_ns_type(T)); public: using ColumnType = typename PrimitiveTypeTraits::ColumnType; @@ -247,6 +247,12 @@ Status DataTypeNumberSerDe::read_column_from_pb(IColumn& column, const PValue for (int i = 0; i < arg.int64_value_size(); ++i) { data[old_column_size + i] = arg.int64_value(i); } + } else if constexpr (T == TYPE_TIMESTAMP_NS) { + column.resize(old_column_size + arg.int64_value_size()); + auto& data = reinterpret_cast(column).get_data(); + for (int i = 0; i < arg.int64_value_size(); ++i) { + data[old_column_size + i] = TimeStampNsValue(arg.int64_value(i)); + } } else if constexpr (T == TYPE_FLOAT) { column.resize(old_column_size + arg.float_value_size()); auto& data = reinterpret_cast(column).get_data(); @@ -332,6 +338,12 @@ Status DataTypeNumberSerDe::write_column_to_pb(const IColumn& column, PValues auto* values = result.mutable_int64_value(); values->Reserve(row_count); values->Add(data.begin() + start, data.begin() + end); + } else if constexpr (T == TYPE_TIMESTAMP_NS) { + ptype->set_id(PGenericType::INT64); + auto* values = result.mutable_int64_value(); + values->Reserve(row_count); + values->Add(reinterpret_cast(data.begin()) + start, + reinterpret_cast(data.begin()) + end); } else if constexpr (T == TYPE_FLOAT) { ptype->set_id(PGenericType::FLOAT); auto* values = result.mutable_float_value(); diff --git a/be/src/core/data_type_serde/data_type_serde.cpp b/be/src/core/data_type_serde/data_type_serde.cpp index bd2a09b6b6e68c..ae09ff04189869 100644 --- a/be/src/core/data_type_serde/data_type_serde.cpp +++ b/be/src/core/data_type_serde/data_type_serde.cpp @@ -291,6 +291,7 @@ const uint8_t* DataTypeSerDe::deserialize_binary_to_column(const uint8_t* data, HANDLE_T_NUM_SERDE(OLAP_FIELD_TYPE_DATEV2, TYPE_DATEV2) HANDLE_T_NUM_SERDE(OLAP_FIELD_TYPE_DATETIMEV2, TYPE_DATETIMEV2) HANDLE_T_DEC_SERDE(OLAP_FIELD_TYPE_DECIMAL, TYPE_DECIMALV2) + HANDLE_T_NUM_SERDE(OLAP_FIELD_TYPE_TIMESTAMP_NS, TYPE_TIMESTAMP_NS) HANDLE_T_DEC_SERDE(OLAP_FIELD_TYPE_DECIMAL32, TYPE_DECIMAL32) HANDLE_T_DEC_SERDE(OLAP_FIELD_TYPE_DECIMAL64, TYPE_DECIMAL64) HANDLE_T_DEC_SERDE(OLAP_FIELD_TYPE_DECIMAL128I, TYPE_DECIMAL128I) @@ -356,6 +357,7 @@ const uint8_t* DataTypeSerDe::deserialize_binary_to_field(const uint8_t* data, F HANDLE_T_NUM_SERDE(OLAP_FIELD_TYPE_DATEV2, TYPE_DATEV2) HANDLE_T_NUM_SERDE(OLAP_FIELD_TYPE_DATETIMEV2, TYPE_DATETIMEV2) HANDLE_T_DEC_SERDE(OLAP_FIELD_TYPE_DECIMAL, TYPE_DECIMALV2) + HANDLE_T_NUM_SERDE(OLAP_FIELD_TYPE_TIMESTAMP_NS, TYPE_TIMESTAMP_NS) HANDLE_T_DEC_SERDE(OLAP_FIELD_TYPE_DECIMAL32, TYPE_DECIMAL32) HANDLE_T_DEC_SERDE(OLAP_FIELD_TYPE_DECIMAL64, TYPE_DECIMAL64) HANDLE_T_DEC_SERDE(OLAP_FIELD_TYPE_DECIMAL128I, TYPE_DECIMAL128I) diff --git a/be/src/core/data_type_serde/data_type_timestamp_ns_serde.cpp b/be/src/core/data_type_serde/data_type_timestamp_ns_serde.cpp new file mode 100644 index 00000000000000..01d9e2244a0470 --- /dev/null +++ b/be/src/core/data_type_serde/data_type_timestamp_ns_serde.cpp @@ -0,0 +1,701 @@ +// 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 "core/data_type_serde/data_type_timestamp_ns_serde.h" + +#include +#include + +#include +#include +#include +#include + +#include "common/config.h" +#include "common/exception.h" +#include "core/assert_cast.h" +#include "core/column/column_nullable.h" +#include "core/column/column_string.h" +#include "core/data_type_serde/arrow_validation.h" +#include "core/data_type_serde/decoded_column_view.h" +#include "core/data_type_serde/orc_serde_utils.h" +#include "core/data_type_serde/parquet_decode_source.h" +#include "core/data_type_serde/parquet_timestamp.h" +#include "core/value/vdatetime_value.h" +#include "exprs/function/cast/cast_to_datetimev2_impl.hpp" +#include "util/mysql_row_buffer.h" +#include "util/unaligned.h" + +namespace doris { +namespace { + +constexpr int64_t NANOS_PER_MILLISECOND = 1000000; +constexpr int64_t NANOS_PER_MICROSECOND = 1000; +constexpr int64_t NANOS_PER_SECOND = TimeStampNsValue::NANOS_PER_SECOND; +constexpr int64_t NANOS_PER_DAY = 86400LL * NANOS_PER_SECOND; + +bool checked_scale_to_nanos(int64_t value, int64_t multiplier, int64_t* result) { + return !__builtin_mul_overflow(value, multiplier, result); +} + +Status utc_epoch_nanos_to_local_epoch_nanos(int64_t source, const cctz::time_zone& timezone, + int64_t* result) { + const TimeStampNsValue source_value(source); + DateV2Value local_value; + local_value.from_unixtime(source_value.epoch_seconds(), timezone); + local_value.set_microsecond(source_value.microsecond()); + TimeStampNsValue target_value; + if (!target_value.from_datetime(local_value, source_value.nanosecond_remainder())) { + return Status::DataQualityError("Timestamp {} is outside TIMESTAMP_NS range", source); + } + *result = target_value.epoch_nanos(); + return Status::OK(); +} + +Status parquet_int96_timestamp_nanos(const ParquetInt96Timestamp& value, int64_t* result) { + static constexpr int32_t JULIAN_EPOCH_OFFSET_DAYS = 2440588; + if (value.nanos_of_day < 0 || value.nanos_of_day >= NANOS_PER_DAY) { + return Status::DataQualityError("Invalid Parquet INT96 nanos-of-day: {}", + value.nanos_of_day); + } + const __int128 days = static_cast(value.julian_day) - JULIAN_EPOCH_OFFSET_DAYS; + const __int128 timestamp_nanos = days * NANOS_PER_DAY + value.nanos_of_day; + if (timestamp_nanos < std::numeric_limits::min() || + timestamp_nanos > std::numeric_limits::max()) { + return Status::DataQualityError( + "Parquet INT96 timestamp is outside the TIMESTAMP_NS range"); + } + *result = static_cast(timestamp_nanos); + return Status::OK(); +} + +Status parquet_timestamp_nanos(ParquetTimeUnit unit, int64_t value, int64_t* result) { + switch (unit) { + case ParquetTimeUnit::MILLIS: + if (!checked_scale_to_nanos(value, NANOS_PER_MILLISECOND, result)) { + return Status::DataQualityError("Parquet timestamp overflows nanoseconds"); + } + return Status::OK(); + case ParquetTimeUnit::MICROS: + if (!checked_scale_to_nanos(value, NANOS_PER_MICROSECOND, result)) { + return Status::DataQualityError("Parquet timestamp overflows nanoseconds"); + } + return Status::OK(); + case ParquetTimeUnit::NANOS: + *result = value; + return Status::OK(); + case ParquetTimeUnit::UNKNOWN: + return Status::NotSupported("TIMESTAMP_NS Parquet timestamp requires a time unit"); + } + __builtin_unreachable(); +} + +Status convert_parquet_timestamp_ns(const ParquetDecodeContext& context, const uint8_t* value, + size_t value_width, int64_t* result) { + Status status; + if (context.physical_type == ParquetPhysicalType::INT96) { + DORIS_CHECK_EQ(value_width, sizeof(ParquetInt96Timestamp)); + status = + parquet_int96_timestamp_nanos(unaligned_load(value), result); + } else { + DORIS_CHECK(context.physical_type == ParquetPhysicalType::INT64); + DORIS_CHECK_EQ(value_width, sizeof(int64_t)); + status = parquet_timestamp_nanos(context.time_unit, unaligned_load(value), result); + } + if (!status.ok() || (context.physical_type != ParquetPhysicalType::INT96 && + !context.timestamp_is_adjusted_to_utc)) { + return status; + } + static const auto utc = cctz::utc_time_zone(); + return utc_epoch_nanos_to_local_epoch_nanos( + *result, context.timezone == nullptr ? utc : *context.timezone, result); +} + +Status decode_timestamp_ns_orc_values(IColumn& column, const OrcDecodedColumnView& view) { + const auto* batch = dynamic_cast(view.batch); + if (batch == nullptr) { + return Status::InternalError("Unexpected ORC timestamp batch type {}", + view.batch->toString()); + } + DORIS_CHECK(view.timezone != nullptr); + auto& data = assert_cast(column).get_data(); + const auto old_size = data.size(); + const auto output_rows = orc_serde_utils::orc_decode_row_count(view.rows, view.selected_rows); + data.resize(old_size + output_rows); + for (size_t row = 0; row < output_rows; ++row) { + const auto source_row = orc_serde_utils::orc_source_row_at(row, view.selected_rows); + if (orc_serde_utils::orc_row_is_null(*view.batch, source_row)) { + data[old_size + row] = TimeStampNsValue {}; + continue; + } + const int64_t nanos = batch->nanoseconds[source_row]; + if (nanos < 0 || nanos >= NANOS_PER_SECOND) { + data.resize(old_size); + return Status::DataQualityError("Invalid ORC timestamp nanoseconds: {}", nanos); + } + DateV2Value datetime; + datetime.from_unixtime(batch->data[source_row], *view.timezone); + datetime.set_microsecond(static_cast(nanos / NANOS_PER_MICROSECOND)); + if (!data[old_size + row].from_datetime( + datetime, static_cast(nanos % NANOS_PER_MICROSECOND))) { + data.resize(old_size); + return Status::DataQualityError( + "Decoded ORC timestamp is outside the TIMESTAMP_NS range"); + } + } + return Status::OK(); +} + +class TimeStampNsParquetConsumer final : public ParquetFixedValueConsumer { +public: + TimeStampNsParquetConsumer(IColumn& column, const ParquetDecodeContext& context, + ParquetMaterializationState* state = nullptr) + : TimeStampNsParquetConsumer(assert_cast(column).get_data(), + context, state) {} + + TimeStampNsParquetConsumer(ColumnTimeStampNs::Container& data, + const ParquetDecodeContext& context, + ParquetMaterializationState* state = nullptr) + : _data(data), _context(context), _state(state) {} + + Status consume(const uint8_t* values, size_t num_values, size_t value_width) override { + const auto old_size = _data.size(); + for (size_t row = 0; row < num_values; ++row) { + int64_t timestamp_nanos = 0; + auto status = convert_parquet_timestamp_ns(_context, values + row * value_width, + value_width, ×tamp_nanos); + if (!status.ok()) { + if (_state != nullptr && _state->mark_conversion_failure(_data.size())) { + _data.emplace_back(); + continue; + } + _data.resize(old_size); + return status; + } + _data.emplace_back(timestamp_nanos); + } + return Status::OK(); + } + +private: + ColumnTimeStampNs::Container& _data; + const ParquetDecodeContext& _context; + ParquetMaterializationState* _state; +}; + +class RejectTimeStampNsBinaryConsumer final : public ParquetBinaryValueConsumer { +public: + Status consume(const StringRef* values, size_t num_values) override { + return Status::NotSupported("Binary Parquet values cannot be materialized as TIMESTAMP_NS"); + } +}; + +class TimeStampNsPredicateParquetConsumer final : public ParquetFixedValueConsumer { +public: + TimeStampNsPredicateParquetConsumer(const ParquetDecodeContext& context, + bool enable_strict_mode, + ParquetLogicalValueConsumer& consumer, + ColumnTimeStampNs::Container& values, + IColumn::Filter& conversion_nulls) + : _context(context), + _enable_strict_mode(enable_strict_mode), + _consumer(consumer), + _values(values), + _conversion_nulls(conversion_nulls) {} + + // The Parquet consumer interface is non-const even though this adapter only mutates its sinks. + // NOLINTNEXTLINE(readability-make-member-function-const) + Status consume(const uint8_t* values, size_t num_values, size_t value_width) override { + _values.clear(); + _conversion_nulls.clear(); + _conversion_nulls.resize_fill(num_values, 0); + ParquetMaterializationState state; + state.enable_strict_mode = _enable_strict_mode; + state.conversion_failure_null_map = &_conversion_nulls; + TimeStampNsParquetConsumer converter(_values, _context, &state); + RETURN_IF_ERROR(converter.consume(values, num_values, value_width)); + return _consumer.consume(reinterpret_cast(_values.data()), num_values, + sizeof(TimeStampNsValue), _conversion_nulls.data()); + } + +private: + const ParquetDecodeContext& _context; + bool _enable_strict_mode; + ParquetLogicalValueConsumer& _consumer; + ColumnTimeStampNs::Container& _values; + IColumn::Filter& _conversion_nulls; +}; + +} // namespace + +Status parse_timestamp_ns(StringRef str, int64_t* epoch_nanos, + const cctz::time_zone* local_time_zone) { + std::string input(str.data, str.size); + const size_t dot = input.rfind('.'); + size_t fraction_begin = std::string::npos; + size_t fraction_end = std::string::npos; + if (dot != std::string::npos && dot + 1 < input.size() && + std::isdigit(static_cast(input[dot + 1]))) { + fraction_begin = dot + 1; + fraction_end = fraction_begin; + while (fraction_end < input.size() && + std::isdigit(static_cast(input[fraction_end]))) { + ++fraction_end; + } + } + + uint32_t nanos = 0; + size_t fraction_length = 0; + if (fraction_begin != std::string::npos) { + fraction_length = fraction_end - fraction_begin; + const size_t copied_digits = + std::min(fraction_length, TimeStampNsValue::FRACTIONAL_DIGITS); + for (size_t i = 0; i < copied_digits; ++i) { + nanos = nanos * 10 + static_cast(input[fraction_begin + i] - '0'); + } + for (size_t i = copied_digits; i < TimeStampNsValue::FRACTIONAL_DIGITS; ++i) { + nanos *= 10; + } + } + + if (fraction_length > TimeStampNsValue::FRACTIONAL_DIGITS && + input[fraction_begin + TimeStampNsValue::FRACTIONAL_DIGITS] >= '5') { + ++nanos; + } + + // Keep the fractional token in place so that the legacy parser validates its position and all + // trailing syntax. Zeroing the digits prevents its scale-0 rounding from changing the second; + // the nanosecond rounding above remains the only source of fractional rounding. + if (fraction_begin != std::string::npos) { + std::fill(input.begin() + fraction_begin, input.begin() + fraction_end, '0'); + } + const StringRef input_ref(input.data(), input.size()); + DateV2Value datetime; + CastParameters params {.status = Status::OK(), .is_strict = true}; + CastToDatetimeV2::from_string_strict_mode( + input_ref, datetime, local_time_zone, 0, params); + if (!params.status.ok()) { + if (dot != std::string::npos) { + return Status::InvalidArgument("Invalid TIMESTAMP_NS value '{}'", + std::string(str.data, str.size)); + } + return params.status; + } + + if (nanos == TimeStampNsValue::NANOS_PER_SECOND) { + if (!datetime.date_add_interval( + TimeInterval {TimeUnit::SECOND, 1, false})) { + return Status::InvalidArgument("TIMESTAMP_NS value overflows while rounding '{}'", + std::string(str.data, str.size)); + } + nanos = 0; + } + datetime.set_microsecond(nanos / NANOS_PER_MICROSECOND); + TimeStampNsValue value; + if (!value.from_datetime(datetime, static_cast(nanos % NANOS_PER_MICROSECOND))) { + return Status::InvalidArgument( + "TIMESTAMP_NS value '{}' is outside [{}, {}]", std::string(str.data, str.size), + TimeStampNsValue(std::numeric_limits::min()).to_string(), + TimeStampNsValue(std::numeric_limits::max()).to_string()); + } + *epoch_nanos = value.epoch_nanos(); + return Status::OK(); +} + +Status DataTypeTimeStampNsSerDe::from_string_batch(const ColumnString& strings, + ColumnNullable& result, + const FormatOptions& options) const { + auto& data = assert_cast(result.get_nested_column()).get_data(); + auto& null_map = result.get_null_map_column().get_data(); + result.resize(strings.size()); + for (size_t i = 0; i < strings.size(); ++i) { + int64_t value = 0; + const auto status = parse_timestamp_ns(strings.get_data_at(i), &value, options.timezone); + null_map[i] = !status.ok(); + data[i] = TimeStampNsValue(value); + } + return Status::OK(); +} + +Status DataTypeTimeStampNsSerDe::from_string_strict_mode_batch( + const ColumnString& strings, IColumn& result, const FormatOptions& options, + const NullMap::value_type* null_map) const { + auto& data = assert_cast(result).get_data(); + result.resize(strings.size()); + for (size_t i = 0; i < strings.size(); ++i) { + if (null_map != nullptr && null_map[i]) { + continue; + } + int64_t value = 0; + RETURN_IF_ERROR(parse_timestamp_ns(strings.get_data_at(i), &value, options.timezone)); + data[i] = TimeStampNsValue(value); + } + return Status::OK(); +} + +Status DataTypeTimeStampNsSerDe::from_string(StringRef& str, IColumn& column, + const FormatOptions& options) const { + int64_t value = 0; + RETURN_IF_ERROR(parse_timestamp_ns(str, &value, options.timezone)); + assert_cast(column).insert_value(TimeStampNsValue(value)); + return Status::OK(); +} + +Status DataTypeTimeStampNsSerDe::from_string_strict_mode(StringRef& str, IColumn& column, + const FormatOptions& options) const { + return from_string(str, column, options); +} + +Status DataTypeTimeStampNsSerDe::serialize_column_to_json(const IColumn& column, int64_t start_idx, + int64_t end_idx, BufferWritable& bw, + FormatOptions& options) const { + SERIALIZE_COLUMN_TO_JSON(); +} + +Status DataTypeTimeStampNsSerDe::serialize_one_cell_to_json(const IColumn& column, int64_t row_num, + BufferWritable& bw, + FormatOptions& options) const { + auto [column_ptr, index] = check_column_const_set_readability(column, row_num); + if (_nesting_level > 1) { + bw.write('"'); + } + const auto value = + assert_cast(*column_ptr) + .get_element(index); + const std::string result = value.to_string(); + bw.write(result.data(), result.size()); + if (_nesting_level > 1) { + bw.write('"'); + } + return Status::OK(); +} + +Status DataTypeTimeStampNsSerDe::deserialize_column_from_json_vector( + IColumn& column, std::vector& slices, uint64_t* num_deserialized, + const FormatOptions& options) const { + DESERIALIZE_COLUMN_FROM_JSON_VECTOR(); + return Status::OK(); +} + +Status DataTypeTimeStampNsSerDe::deserialize_one_cell_from_json( + IColumn& column, Slice& slice, const FormatOptions& options) const { + if (_nesting_level > 1) { + slice.trim_quote(); + } + StringRef str(slice.data, slice.size); + return from_string(str, column, options); +} + +Status DataTypeTimeStampNsSerDe::deserialize_column_from_jsonb(IColumn& column, + const JsonbValue* jsonb_value, + CastParameters& cast_params) const { + DORIS_CHECK(jsonb_value->isString()); + return parse_column_from_jsonb_string(column, jsonb_value, cast_params); +} + +Status DataTypeTimeStampNsSerDe::deserialize_column_from_jsonb_vector( + ColumnNullable& column_to, const ColumnString& column_from, + CastParameters& cast_params) const { + return DataTypeSerDe::deserialize_column_from_jsonb_vector(column_to, column_from, cast_params); +} + +Status DataTypeTimeStampNsSerDe::write_column_to_arrow(const IColumn& column, + const NullMap* null_map, + arrow::ArrayBuilder* array_builder, + int64_t start, int64_t end, + const cctz::time_zone& ctz) const { + const auto& data = assert_cast(column).get_data(); + auto& builder = assert_cast(*array_builder); + const auto type = std::static_pointer_cast(array_builder->type()); + const auto& timezone = type->timezone().empty() ? cctz::utc_time_zone() : ctz; + int64_t divisor = 1; + switch (type->unit()) { + case arrow::TimeUnit::SECOND: + divisor = NANOS_PER_SECOND; + break; + case arrow::TimeUnit::MILLI: + divisor = NANOS_PER_MILLISECOND; + break; + case arrow::TimeUnit::MICRO: + divisor = NANOS_PER_MICROSECOND; + break; + case arrow::TimeUnit::NANO: + break; + } + for (int64_t row = start; row < end; ++row) { + if (null_map != nullptr && (*null_map)[row]) { + RETURN_IF_ERROR(checkArrowStatus(builder.AppendNull(), column, *array_builder)); + continue; + } + auto datetime = data[row].to_datetime(); + int64_t epoch_seconds = 0; + datetime.unix_timestamp(&epoch_seconds, timezone); + const __int128 epoch_nanos = + static_cast<__int128>(epoch_seconds) * NANOS_PER_SECOND + data[row].nanosecond(); + __int128 arrow_value = epoch_nanos / divisor; + if (epoch_nanos < 0 && epoch_nanos % divisor != 0) { + --arrow_value; + } + if (arrow_value < std::numeric_limits::min() || + arrow_value > std::numeric_limits::max()) { + return Status::DataQualityError("TIMESTAMP_NS {} overflows Arrow timestamp unit {}", + data[row].to_string(), static_cast(type->unit())); + } + RETURN_IF_ERROR(checkArrowStatus(builder.Append(static_cast(arrow_value)), column, + *array_builder)); + } + return Status::OK(); +} + +Status DataTypeTimeStampNsSerDe::read_column_from_arrow(IColumn& column, + const arrow::Array* arrow_array, + int64_t start, int64_t end, + const cctz::time_zone& ctz) const { + if (config::enable_arrow_input_validation) { + check_arrow_array_range(*arrow_array, start, end); + } + if (arrow_array->type()->id() != arrow::Type::TIMESTAMP) { + return Status::InvalidArgument("Cannot convert Arrow type {} to TIMESTAMP_NS", + arrow_array->type()->ToString()); + } + const auto* timestamps = assert_cast(arrow_array); + if (config::enable_arrow_input_validation) { + check_arrow_fixed_width_buffer(*timestamps, sizeof(arrow::TimestampArray::value_type)); + } + const auto type = std::static_pointer_cast(arrow_array->type()); + int64_t multiplier = 1; + switch (type->unit()) { + case arrow::TimeUnit::SECOND: + multiplier = NANOS_PER_SECOND; + break; + case arrow::TimeUnit::MILLI: + multiplier = NANOS_PER_MILLISECOND; + break; + case arrow::TimeUnit::MICRO: + multiplier = NANOS_PER_MICROSECOND; + break; + case arrow::TimeUnit::NANO: + break; + } + auto& data = assert_cast(column).get_data(); + const auto old_size = data.size(); + for (int64_t row = start; row < end; ++row) { + if (timestamps->IsNull(row)) { + data.emplace_back(); + continue; + } + int64_t nanos = 0; + const int64_t value = timestamps->Value(row); + if (!checked_scale_to_nanos(value, multiplier, &nanos)) { + data.resize(old_size); + return Status::DataQualityError("Arrow timestamp {} overflows TIMESTAMP_NS", value); + } + if (!type->timezone().empty()) { + const auto status = utc_epoch_nanos_to_local_epoch_nanos(nanos, ctz, &nanos); + if (!status.ok()) { + data.resize(old_size); + return status; + } + } + data.emplace_back(nanos); + } + return Status::OK(); +} + +Status DataTypeTimeStampNsSerDe::read_column_from_decoded_values( + IColumn& column, const DecodedColumnView& view) const { + if (view.value_kind != DecodedValueKind::INT64 && view.value_kind != DecodedValueKind::INT96) { + return decoded_column_view_handle_conversion_failure( + column, view, + Status::NotSupported("TIMESTAMP_NS decoded reader expects INT64 or INT96 source")); + } + if (view.values == nullptr && decoded_column_view_has_non_null_value(view)) { + return Status::Corruption("Decoded value buffer is null for {}", column.get_name()); + } + auto& data = assert_cast(column).get_data(); + const auto old_size = data.size(); + static const auto utc = cctz::utc_time_zone(); + const auto& timezone = view.timezone == nullptr ? utc : *view.timezone; + for (int64_t row = 0; row < view.row_count; ++row) { + if (decoded_column_view_row_is_null(view, row)) { + data.push_back(TimeStampNsValue(0)); + continue; + } + int64_t nanos = 0; + Status status; + if (view.value_kind == DecodedValueKind::INT96) { + status = parquet_int96_timestamp_nanos( + reinterpret_cast(view.values)[row], &nanos); + } else { + ParquetTimeUnit unit = ParquetTimeUnit::UNKNOWN; + if (view.time_unit == DecodedTimeUnit::MILLIS) { + unit = ParquetTimeUnit::MILLIS; + } else if (view.time_unit == DecodedTimeUnit::MICROS) { + unit = ParquetTimeUnit::MICROS; + } else if (view.time_unit == DecodedTimeUnit::NANOS) { + unit = ParquetTimeUnit::NANOS; + } + status = parquet_timestamp_nanos( + unit, reinterpret_cast(view.values)[row], &nanos); + } + if (status.ok() && + (view.value_kind == DecodedValueKind::INT96 || view.timestamp_is_adjusted_to_utc)) { + status = utc_epoch_nanos_to_local_epoch_nanos(nanos, timezone, &nanos); + } + if (!status.ok()) { + if (decoded_column_view_can_null_on_conversion_failure(view)) { + decoded_column_view_insert_null_on_conversion_failure(column, view, row); + continue; + } + data.resize(old_size); + return status; + } + data.emplace_back(nanos); + } + return Status::OK(); +} + +Status DataTypeTimeStampNsSerDe::read_parquet_dictionary( + IColumn& column, ParquetDecodeSource& source, const ParquetDecodeContext& context) const { + TimeStampNsParquetConsumer consumer(column, context); + RejectTimeStampNsBinaryConsumer binary_consumer; + return source.decode_dictionary(consumer, binary_consumer); +} + +Status DataTypeTimeStampNsSerDe::read_column_from_parquet( + IColumn& column, ParquetDecodeSource& source, const ParquetDecodeContext& context, + size_t num_values, ParquetMaterializationState& state) const { + if (context.physical_type != ParquetPhysicalType::INT64 && + context.physical_type != ParquetPhysicalType::INT96) { + return Status::NotSupported("TIMESTAMP_NS expects Parquet INT64 or INT96"); + } + TimeStampNsParquetConsumer consumer(column, context, &state); + if (context.encoding != ParquetValueEncoding::DICTIONARY) { + return source.decode_fixed_values(num_values, consumer); + } + if (state.dictionary_generation != source.dictionary_generation()) { + state.typed_dictionary = column.clone_empty(); + auto* output_null_map = state.begin_dictionary_conversion(source.dictionary_size()); + TimeStampNsParquetConsumer dictionary_consumer(*state.typed_dictionary, context, &state); + RejectTimeStampNsBinaryConsumer binary_consumer; + const auto status = source.decode_dictionary(dictionary_consumer, binary_consumer); + state.end_dictionary_conversion(output_null_map); + RETURN_IF_ERROR(status); + DORIS_CHECK_EQ(state.typed_dictionary->size(), source.dictionary_size()); + state.dictionary_generation = source.dictionary_generation(); + } + return state.materialize_dictionary(column, source, num_values); +} + +bool DataTypeTimeStampNsSerDe::supports_parquet_raw_predicate( + const ParquetDecodeContext& context) const { + return context.encoding != ParquetValueEncoding::DICTIONARY && + (context.physical_type == ParquetPhysicalType::INT64 || + context.physical_type == ParquetPhysicalType::INT96) && + context.logical_type == ParquetLogicalType::TIMESTAMP; +} + +Status DataTypeTimeStampNsSerDe::read_parquet_raw_predicate( + ParquetDecodeSource& source, const ParquetDecodeContext& context, size_t num_values, + bool enable_strict_mode, ParquetLogicalValueConsumer& consumer) const { + if (!supports_parquet_raw_predicate(context)) { + return Status::NotSupported( + "Unsupported Parquet raw predicate conversion for TIMESTAMP_NS"); + } + TimeStampNsPredicateParquetConsumer predicate_consumer(context, enable_strict_mode, consumer, + _parquet_predicate_values, + _parquet_predicate_nulls); + return source.decode_fixed_values(num_values, predicate_consumer); +} + +Status DataTypeTimeStampNsSerDe::write_column_to_mysql_binary(const IColumn& column, + MysqlRowBinaryBuffer& row_buffer, + int64_t row_idx, bool col_const, + const FormatOptions& options) const { + const auto& data = assert_cast(column).get_data(); + const auto index = index_check_const(row_idx, col_const); + const auto value = TimeStampNsValue(data[index]).to_string(); + if (row_buffer.push_string(value.data(), value.size()) != 0) { + return Status::InternalError("pack MySQL TIMESTAMP_NS buffer failed"); + } + return Status::OK(); +} + +Status DataTypeTimeStampNsSerDe::write_column_to_orc(const std::string& timezone, + const IColumn& column, const NullMap* null_map, + orc::ColumnVectorBatch* orc_col_batch, + int64_t start, int64_t end, Arena& arena, + const FormatOptions& options) const { + const auto& data = assert_cast(column).get_data(); + auto* batch = dynamic_cast<::orc::TimestampVectorBatch*>(orc_col_batch); + DORIS_CHECK(batch != nullptr); + for (int64_t row = start; row < end; ++row) { + if (batch->notNull[row] == 0) { + continue; + } + auto datetime = data[row].to_datetime(); + int64_t epoch_seconds = 0; + if (!datetime.unix_timestamp(&epoch_seconds, timezone)) { + return Status::DataQualityError("Cannot write TIMESTAMP_NS {} in timezone {} to ORC", + data[row].to_string(), timezone); + } + batch->data[row] = epoch_seconds; + batch->nanoseconds[row] = data[row].nanosecond(); + } + batch->numElements = end - start; + return Status::OK(); +} + +Status DataTypeTimeStampNsSerDe::read_column_from_orc(IColumn& column, + const OrcDecodedColumnView& view) const { + DORIS_CHECK(view.file_type != nullptr); + DORIS_CHECK(view.batch != nullptr); + const auto kind = view.file_type->getKind(); + DORIS_CHECK(kind == ::orc::TypeKind::TIMESTAMP || kind == ::orc::TypeKind::TIMESTAMP_INSTANT); + DORIS_CHECK(view.timezone != nullptr); + if (orc_serde_utils::orc_decode_row_count(view.rows, view.selected_rows) == 0) { + return Status::OK(); + } + return decode_timestamp_ns_orc_values(column, view); +} + +void DataTypeTimeStampNsSerDe::write_one_cell_to_binary(const IColumn& src_column, + ColumnString::Chars& chars, + int64_t row_num) const { + const auto type = static_cast(FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS); + constexpr auto scale = static_cast(9); + const auto value = assert_cast(src_column).get_element(row_num); + const size_t old_size = chars.size(); + chars.resize(old_size + sizeof(type) + sizeof(scale) + sizeof(value)); + memcpy(chars.data() + old_size, &type, sizeof(type)); + memcpy(chars.data() + old_size + sizeof(type), &scale, sizeof(scale)); + memcpy(chars.data() + old_size + sizeof(type) + sizeof(scale), &value, sizeof(value)); +} + +std::string DataTypeTimeStampNsSerDe::to_olap_string(const Field& field) const { + return field.get().to_string(); +} + +Status DataTypeTimeStampNsSerDe::from_olap_string(const std::string& str, Field& field, + const FormatOptions& options) const { + int64_t value = 0; + RETURN_IF_ERROR(parse_timestamp_ns(StringRef(str.data(), str.size()), &value)); + field = Field::create_field(TimeStampNsValue(value)); + return Status::OK(); +} + +} // namespace doris diff --git a/be/src/core/data_type_serde/data_type_timestamp_ns_serde.h b/be/src/core/data_type_serde/data_type_timestamp_ns_serde.h new file mode 100644 index 00000000000000..d8de084c638651 --- /dev/null +++ b/be/src/core/data_type_serde/data_type_timestamp_ns_serde.h @@ -0,0 +1,111 @@ +// 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. + +#pragma once + +#include "core/data_type_serde/data_type_number_serde.h" +#include "core/value/timestamp_ns_value.h" + +namespace doris { + +Status parse_timestamp_ns(StringRef str, int64_t* epoch_nanos, + const cctz::time_zone* local_time_zone = nullptr); + +class DataTypeTimeStampNsSerDe final + : public DataTypeNumberSerDe { +public: + explicit DataTypeTimeStampNsSerDe(int nesting_level = 1) + : DataTypeNumberSerDe(nesting_level) {} + + Status from_string_batch(const ColumnString& str, ColumnNullable& column, + const FormatOptions& options) const override; + Status from_string_strict_mode_batch( + const ColumnString& str, IColumn& column, const FormatOptions& options, + const NullMap::value_type* null_map = nullptr) const override; + Status from_string(StringRef& str, IColumn& column, + const FormatOptions& options) const override; + Status from_string_strict_mode(StringRef& str, IColumn& column, + const FormatOptions& options) const override; + + Status serialize_one_cell_to_json(const IColumn& column, int64_t row_num, BufferWritable& bw, + FormatOptions& options) const override; + Status serialize_column_to_json(const IColumn& column, int64_t start_idx, int64_t end_idx, + BufferWritable& bw, FormatOptions& options) const override; + Status deserialize_one_cell_from_json(IColumn& column, Slice& slice, + const FormatOptions& options) const override; + Status deserialize_column_from_json_vector(IColumn& column, std::vector& slices, + uint64_t* num_deserialized, + const FormatOptions& options) const override; + Status deserialize_column_from_jsonb(IColumn& column, const JsonbValue* jsonb_value, + CastParameters& cast_params) const override; + Status deserialize_column_from_jsonb_vector(ColumnNullable& column_to, + const ColumnString& column_from, + CastParameters& cast_params) const override; + + Status write_column_to_arrow(const IColumn& column, const NullMap* null_map, + arrow::ArrayBuilder* array_builder, int64_t start, int64_t end, + const cctz::time_zone& ctz) const override; + Status read_column_from_arrow(IColumn& column, const arrow::Array* arrow_array, int64_t start, + int64_t end, const cctz::time_zone& ctz) const override; + Status read_column_from_decoded_values(IColumn& column, + const DecodedColumnView& view) const override; + Status read_column_from_parquet(IColumn& column, ParquetDecodeSource& source, + const ParquetDecodeContext& context, size_t num_values, + ParquetMaterializationState& state) const override; + bool supports_parquet_raw_predicate(const ParquetDecodeContext& context) const override; + Status read_parquet_raw_predicate(ParquetDecodeSource& source, + const ParquetDecodeContext& context, size_t num_values, + bool enable_strict_mode, + ParquetLogicalValueConsumer& consumer) const override; + Status read_parquet_dictionary(IColumn& column, ParquetDecodeSource& source, + const ParquetDecodeContext& context) const override; + size_t retained_parquet_raw_predicate_scratch_bytes() const override { + return _parquet_predicate_values.capacity() * sizeof(TimeStampNsValue) + + _parquet_predicate_nulls.capacity(); + } + size_t active_parquet_raw_predicate_scratch_bytes() const override { + return _parquet_predicate_values.size() * sizeof(TimeStampNsValue) + + _parquet_predicate_nulls.size(); + } + void release_parquet_raw_predicate_scratch(size_t max_retained_bytes) const override { + if (_parquet_predicate_values.capacity() * sizeof(TimeStampNsValue) > max_retained_bytes) { + ColumnTimeStampNs::Container().swap(_parquet_predicate_values); + } + if (_parquet_predicate_nulls.capacity() > max_retained_bytes) { + IColumn::Filter().swap(_parquet_predicate_nulls); + } + } + Status read_column_from_orc(IColumn& column, const OrcDecodedColumnView& view) const override; + Status write_column_to_mysql_binary(const IColumn& column, MysqlRowBinaryBuffer& row_buffer, + int64_t row_idx, bool col_const, + const FormatOptions& options) const override; + Status write_column_to_orc(const std::string& timezone, const IColumn& column, + const NullMap* null_map, orc::ColumnVectorBatch* orc_col_batch, + int64_t start, int64_t end, Arena& arena, + const FormatOptions& options) const override; + + void write_one_cell_to_binary(const IColumn& src_column, ColumnString::Chars& chars, + int64_t row_num) const override; + int get_scale() const override { return TimeStampNsValue::FRACTIONAL_DIGITS; } + std::string to_olap_string(const Field& field) const override; + +protected: + Status from_olap_string(const std::string& str, Field& field, + const FormatOptions& options) const override; +}; + +} // namespace doris diff --git a/be/src/core/data_type_serde/parquet_decode_source.cpp b/be/src/core/data_type_serde/parquet_decode_source.cpp index 68df6074ddfa7a..834eeb96965e0c 100644 --- a/be/src/core/data_type_serde/parquet_decode_source.cpp +++ b/be/src/core/data_type_serde/parquet_decode_source.cpp @@ -116,6 +116,7 @@ bool try_simd_insert_parquet_dictionary_indices(IColumn& destination, const ICol TRY_PARQUET_GATHER(TYPE_DATETIME); TRY_PARQUET_GATHER(TYPE_DATEV2); TRY_PARQUET_GATHER(TYPE_DATETIMEV2); + TRY_PARQUET_GATHER(TYPE_TIMESTAMP_NS); TRY_PARQUET_GATHER(TYPE_TIMESTAMPTZ); TRY_PARQUET_GATHER(TYPE_IPV4); TRY_PARQUET_GATHER(TYPE_TIMEV2); diff --git a/be/src/core/field.cpp b/be/src/core/field.cpp index f63aaf8227a7c6..a21367e0dc2000 100644 --- a/be/src/core/field.cpp +++ b/be/src/core/field.cpp @@ -124,6 +124,9 @@ void Field::create(Field&& field) { case PrimitiveType::TYPE_DATETIMEV2: create_concrete(std::move(field.template get())); return; + case PrimitiveType::TYPE_TIMESTAMP_NS: + create_concrete(std::move(field.template get())); + return; case PrimitiveType::TYPE_DATEV2: create_concrete(std::move(field.template get())); return; @@ -253,6 +256,9 @@ void Field::create(const Field& field) { case PrimitiveType::TYPE_DATETIMEV2: create_concrete(field.template get()); return; + case PrimitiveType::TYPE_TIMESTAMP_NS: + create_concrete(field.template get()); + return; case PrimitiveType::TYPE_DATEV2: create_concrete(field.template get()); return; @@ -414,6 +420,9 @@ void Field::assign(Field&& field) { case PrimitiveType::TYPE_DATETIMEV2: assign_concrete(std::move(field.template get())); return; + case PrimitiveType::TYPE_TIMESTAMP_NS: + assign_concrete(std::move(field.template get())); + return; case PrimitiveType::TYPE_DATETIME: assign_concrete(std::move(field.template get())); return; @@ -523,6 +532,9 @@ void Field::assign(const Field& field) { case PrimitiveType::TYPE_DATETIMEV2: assign_concrete(field.template get()); return; + case PrimitiveType::TYPE_TIMESTAMP_NS: + assign_concrete(field.template get()); + return; case PrimitiveType::TYPE_DATETIME: assign_concrete(field.template get()); return; @@ -708,6 +720,9 @@ std::strong_ordering Field::operator<=>(const Field& rhs) const { case PrimitiveType::TYPE_DATETIMEV2: return get().to_date_int_val() <=> rhs.get().to_date_int_val(); + case PrimitiveType::TYPE_TIMESTAMP_NS: + return get() <=> + rhs.get(); case PrimitiveType::TYPE_DATEV2: return get().to_date_int_val() <=> rhs.get().to_date_int_val(); @@ -826,6 +841,7 @@ std::string_view Field::as_string_view() const { // MATCH_PRIMITIVE_TYPE(TYPE_QUANTILE_STATE); MATCH_PRIMITIVE_TYPE(TYPE_DATEV2); MATCH_PRIMITIVE_TYPE(TYPE_DATETIMEV2); + MATCH_PRIMITIVE_TYPE(TYPE_TIMESTAMP_NS); MATCH_PRIMITIVE_TYPE(TYPE_TIMEV2); MATCH_PRIMITIVE_TYPE(TYPE_DECIMAL32); MATCH_PRIMITIVE_TYPE(TYPE_DECIMAL64); @@ -883,6 +899,8 @@ std::string Field::to_debug_string(int scale) const { return CastToString::from_datev2(get()); case PrimitiveType::TYPE_DATETIMEV2: return CastToString::from_datetimev2(get(), scale); + case PrimitiveType::TYPE_TIMESTAMP_NS: + return get().to_string(); case PrimitiveType::TYPE_TIMESTAMPTZ: return CastToString::from_timestamptz(get(), scale); case PrimitiveType::TYPE_DECIMALV2: @@ -927,6 +945,8 @@ std::string Field::to_debug_string(int scale) const { typename PrimitiveTypeTraits::CppType && rhs); \ template void Field::FUNC_NAME( \ typename PrimitiveTypeTraits::CppType && rhs); \ + template void Field::FUNC_NAME( \ + typename PrimitiveTypeTraits::CppType && rhs); \ template void Field::FUNC_NAME( \ typename PrimitiveTypeTraits::CppType && rhs); \ template void Field::FUNC_NAME( \ @@ -973,6 +993,8 @@ std::string Field::to_debug_string(int scale) const { const typename PrimitiveTypeTraits::CppType& rhs); \ template void Field::FUNC_NAME( \ const typename PrimitiveTypeTraits::CppType& rhs); \ + template void Field::FUNC_NAME( \ + const typename PrimitiveTypeTraits::CppType& rhs); \ template void Field::FUNC_NAME( \ const typename PrimitiveTypeTraits::CppType& rhs); \ template void Field::FUNC_NAME( \ @@ -1070,6 +1092,7 @@ DECLARE_FUNCTION(TYPE_DATE) DECLARE_FUNCTION(TYPE_DATETIME) DECLARE_FUNCTION(TYPE_DATEV2) DECLARE_FUNCTION(TYPE_DATETIMEV2) +DECLARE_FUNCTION(TYPE_TIMESTAMP_NS) DECLARE_FUNCTION(TYPE_TIMESTAMPTZ) DECLARE_FUNCTION(TYPE_DECIMAL32) DECLARE_FUNCTION(TYPE_DECIMAL64) diff --git a/be/src/core/type_limit.h b/be/src/core/type_limit.h index 824433a03191dc..7a286470f5a25d 100644 --- a/be/src/core/type_limit.h +++ b/be/src/core/type_limit.h @@ -20,6 +20,7 @@ #include "core/extended_types.h" #include "core/string_ref.h" #include "core/value/decimalv2_value.h" +#include "core/value/timestamp_ns_value.h" #include "core/value/timestamptz_value.h" namespace doris { @@ -118,6 +119,12 @@ struct type_limit> { } }; +template <> +struct type_limit { + static TimeStampNsValue min() { return TimeStampNsValue(std::numeric_limits::min()); } + static TimeStampNsValue max() { return TimeStampNsValue(std::numeric_limits::max()); } +}; + template <> struct type_limit { static TimestampTzValue min() { diff --git a/be/src/core/value/timestamp_ns_value.cpp b/be/src/core/value/timestamp_ns_value.cpp new file mode 100644 index 00000000000000..e7b8554421c26a --- /dev/null +++ b/be/src/core/value/timestamp_ns_value.cpp @@ -0,0 +1,68 @@ +// 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 "core/value/timestamp_ns_value.h" + +#include + +#include "exec/common/int_exp.h" + +namespace doris { + +DateV2Value TimeStampNsValue::to_datetime() const { + // epoch_seconds() is floor-divided, so set_microsecond() always receives the first six digits + // of a non-negative fractional second even for timestamps before the epoch. + DateV2Value value; + value.from_unixtime(epoch_seconds(), cctz::utc_time_zone()); + value.set_microsecond(microsecond()); + return value; +} + +bool TimeStampNsValue::from_datetime(const DateV2Value& value, + uint16_t nanosecond_remainder) { + DORIS_CHECK_LE(nanosecond_remainder, 999); + int64_t seconds = 0; + value.unix_timestamp(&seconds, cctz::utc_time_zone()); + // The civil adapter and remainder form one exact epoch-nanosecond value. Int128 is required: + // valid boundary dates overflow Int64 during the intermediate seconds-to-nanoseconds product. + const __int128 epoch_nanos = static_cast<__int128>(seconds) * NANOS_PER_SECOND + + static_cast<__int128>(value.microsecond()) * 1000 + + nanosecond_remainder; + if (epoch_nanos < std::numeric_limits::min() || + epoch_nanos > std::numeric_limits::max()) { + return false; + } + _epoch_nanos = static_cast(epoch_nanos); + return true; +} + +int32_t TimeStampNsValue::to_buffer(char* buffer) const { + const auto value = to_datetime(); + const int32_t base_length = value.to_buffer(buffer, 0); + buffer[base_length] = '.'; + uint32_t nanos = nanosecond(); + // Consume the fraction from most significant to least significant digit. Deliberately do not + // round here: type normalization happens while parsing/casting, before a value is stored. + for (int i = 0; i < FRACTIONAL_DIGITS; ++i) { + const auto divisor = static_cast(int_exp10(FRACTIONAL_DIGITS - 1 - i)); + buffer[base_length + 1 + i] = static_cast('0' + nanos / divisor); + nanos %= divisor; + } + return base_length + 1 + FRACTIONAL_DIGITS; +} + +} // namespace doris diff --git a/be/src/core/value/timestamp_ns_value.h b/be/src/core/value/timestamp_ns_value.h new file mode 100644 index 00000000000000..e6ae88ddd6ff93 --- /dev/null +++ b/be/src/core/value/timestamp_ns_value.h @@ -0,0 +1,286 @@ +// 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. + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "core/value/vdatetime_value.h" + +namespace doris { + +// TIMESTAMP_NS is represented by a signed Int64 count of nanoseconds from the Unix epoch. The +// complete Int64 domain is valid, giving the exact range +// [1677-09-21 00:12:43.145224192, 2262-04-11 23:47:16.854775807]. The SQL type is timezone-naive: +// UTC below is only a deterministic bridge between the integer and civil calendar fields, and +// must not apply the session time zone. +// +// Keep this class an Int64-sized trivially-copyable value. Columns, storage encodings, hashing, +// and SIMD paths rely on being able to move its bytes exactly like an Int64. +class TimeStampNsValue { +public: + static constexpr int FRACTIONAL_DIGITS = 9; + static constexpr int64_t NANOS_PER_SECOND = 1000000000; + static constexpr int64_t NANOS_PER_MILLISECOND = 1000000; + static constexpr int64_t NANOS_PER_MICROSECOND = 1000; + + constexpr TimeStampNsValue() = default; + explicit constexpr TimeStampNsValue(int64_t epoch_nanos) : _epoch_nanos(epoch_nanos) {} + + // This is the raw physical key, not the packed civil layout used by DATETIMEV2. + constexpr int64_t to_date_int_val() const { return _epoch_nanos; } + constexpr int64_t epoch_nanos() const { return _epoch_nanos; } + + // Split epoch nanoseconds using floor division so the fractional component is always + // non-negative. For example, -1ns becomes second -1 plus nanosecond 999,999,999 rather than + // second 0 plus a negative fraction. + int64_t epoch_seconds() const { + int64_t seconds = _epoch_nanos / NANOS_PER_SECOND; + if (_epoch_nanos % NANOS_PER_SECOND < 0) { + --seconds; + } + return seconds; + } + + uint32_t nanosecond() const { + int64_t nanos = _epoch_nanos % NANOS_PER_SECOND; + if (nanos < 0) { + nanos += NANOS_PER_SECOND; + } + return static_cast(nanos); + } + + uint32_t microsecond() const { return nanosecond() / 1000; } + uint16_t nanosecond_remainder() const { return static_cast(nanosecond() % 1000); } + + // DATETIMEV2 is used only as a civil-calendar adapter. It carries the first six fractional + // digits; callers must preserve nanosecond_remainder() separately when the operation should + // not discard the final three digits. + DateV2Value to_datetime() const; + bool from_datetime(const DateV2Value& value, + uint16_t nanosecond_remainder = 0); + + // Calendar functions use the packed DATETIMEV2 value as a civil-field adapter. Keep all + // timezone handling outside this class: TIMESTAMP_NS itself is timezone-naive. + uint16_t year() const { return to_datetime().year(); } + uint8_t month() const { return to_datetime().month(); } + uint8_t day() const { return to_datetime().day(); } + uint8_t hour() const { return to_datetime().hour(); } + uint8_t minute() const { return to_datetime().minute(); } + uint8_t second() const { return to_datetime().second(); } + int quarter() const { return to_datetime().quarter(); } + int64_t daynr() const { return to_datetime().daynr(); } + uint16_t year_of_week() const { return to_datetime().year_of_week(); } + uint8_t week(uint8_t mode) const { return to_datetime().week(mode); } + uint32_t year_week(uint8_t mode) const { return to_datetime().year_week(mode); } + int day_of_year() const { return to_datetime().day_of_year(); } + int day_of_week() const { return to_datetime().day_of_week(); } + uint8_t weekday() const { return to_datetime().weekday(); } + int64_t time_part_to_seconds() const { return to_datetime().time_part_to_seconds(); } + int64_t time_part_to_microsecond() const { + return time_part_to_seconds() * 1000000 + microsecond(); + } + + template + int64_t time_part_diff_in_ms(const RHS& rhs) const { + return time_part_to_microsecond() - rhs.time_part_to_microsecond(); + } + + // This intentionally compares integral civil seconds and ignores fractional seconds. It is + // the contract used by sequence_match's second-based pattern conditions. + template + int64_t datetime_diff_in_seconds(const RHS& rhs) const { + return (daynr() - rhs.daynr()) * SECOND_PER_HOUR * HOUR_PER_DAY + time_part_to_seconds() - + rhs.time_part_to_seconds(); + } + + template + int64_t datetime_diff_in_microseconds(const RHS& rhs) const { + if constexpr (std::is_same_v, TimeStampNsValue>) { + return static_cast((static_cast<__int128>(_epoch_nanos) - rhs._epoch_nanos) / + NANOS_PER_MICROSECOND); + } + return (daynr() - rhs.daynr()) * HOUR_PER_DAY * SECOND_PER_HOUR * MS_PER_SECOND + + time_part_diff_in_ms(rhs); + } + + template + int32_t date_diff_in_days(const RHS& rhs) const { + return static_cast(daynr() - rhs.daynr()); + } + + int32_t date_diff_in_days_round_to_zero_by_time(const auto& rhs) const { + int32_t days = date_diff_in_days(rhs); + const int64_t time_diff = time_part_diff_in_ms(rhs); + if (days > 0 && time_diff < 0) { + --days; + } else if (days < 0 && time_diff > 0) { + ++days; + } + return days; + } + + const char* day_name_with_locale(const char* const* day_names) const { + return to_datetime().day_name_with_locale(day_names); + } + const char* month_name_with_locale(const char* const* month_names) const { + return to_datetime().month_name_with_locale(month_names); + } + bool to_format_string_conservative(const char* format, size_t len, char* to, + size_t max_valid_length) const { + return to_datetime().to_format_string_conservative(format, len, to, max_valid_length); + } + + bool is_valid_date() const { return true; } + + // Calendar arithmetic preserves all nine fractional digits. The packed adapter carries the + // leading microseconds and the explicit remainder carries the final three nanoseconds. + template + bool date_add_interval(const TimeInterval& interval) { + auto value = to_datetime(); + const uint16_t remainder = nanosecond_remainder(); + if (!value.template date_add_interval(interval)) { + return false; + } + return from_datetime(value, remainder); + } + + // Truncation deliberately discards every field below unit. Conversion back detects the two + // civil boundary days whose midnight lies outside the signed epoch-nanosecond range. + template + bool datetime_trunc() { + auto value = to_datetime(); + if (!value.template datetime_trunc()) { + return false; + } + return from_datetime(value); + } + + // TIMESTAMP_NS has no configurable scale. Formatting always emits all nine fractional digits, + // including trailing zeros, so every output path exposes the same fixed-width representation. + int32_t to_buffer(char* buffer) const; + char* to_string(char* buffer) const { + const int32_t length = to_buffer(buffer); + buffer[length] = '\0'; + return buffer + length + 1; + } + std::string to_string() const { + char buffer[40]; + const int32_t length = to_buffer(buffer); + return {buffer, static_cast(length)}; + } + + auto operator<=>(const TimeStampNsValue&) const = default; + + TimeStampNsValue& operator+=(int64_t seconds) { + int64_t delta = 0; + DORIS_CHECK(!__builtin_mul_overflow(seconds, NANOS_PER_SECOND, &delta)); + DORIS_CHECK(!__builtin_add_overflow(_epoch_nanos, delta, &_epoch_nanos)); + return *this; + } + + TimeStampNsValue& operator-=(int64_t seconds) { + DORIS_CHECK_NE(seconds, std::numeric_limits::min()); + return *this += -seconds; + } + + uint32_t hash(int seed) const { + return HashUtil::hash(&_epoch_nanos, sizeof(_epoch_nanos), seed); + } + +private: + int64_t _epoch_nanos = 0; +}; + +static_assert(sizeof(TimeStampNsValue) == sizeof(int64_t)); +static_assert(std::is_trivially_copyable_v); + +// Whole-unit differences follow DATETIMEV2 semantics: calendar units compare civil fields while +// elapsed units use the exact signed epoch-nanosecond difference and truncate toward zero. +template +int64_t datetime_diff(const TimeStampNsValue& ts_value1, const TimeStampNsValue& ts_value2) { + const auto time_key = [](const TimeStampNsValue& value, bool include_month) { + int64_t result = include_month ? value.month() : 0; + result = result * 32 + value.day(); + result = result * 24 + value.hour(); + result = result * 60 + value.minute(); + result = result * 60 + value.second(); + return result * TimeStampNsValue::NANOS_PER_SECOND + value.nanosecond(); + }; + if constexpr (UNIT == YEAR) { + int year = ts_value2.year() - ts_value1.year(); + const int64_t remainder1 = time_key(ts_value1, true); + const int64_t remainder2 = time_key(ts_value2, true); + if (year > 0) { + year -= remainder2 < remainder1; + } else if (year < 0) { + year += remainder2 > remainder1; + } + return year; + } else if constexpr (UNIT == QUARTER || UNIT == MONTH) { + int month = (ts_value2.year() - ts_value1.year()) * 12 + + (ts_value2.month() - ts_value1.month()); + const int64_t remainder1 = time_key(ts_value1, false); + const int64_t remainder2 = time_key(ts_value2, false); + if (month > 0) { + month -= remainder2 < remainder1; + } else if (month < 0) { + month += remainder2 > remainder1; + } + return UNIT == QUARTER ? month / 3 : month; + } else if constexpr (UNIT == WEEK || UNIT == DAY) { + int64_t day = ts_value2.daynr() - ts_value1.daynr(); + const int64_t time1 = + ts_value1.time_part_to_seconds() * TimeStampNsValue::NANOS_PER_SECOND + + ts_value1.nanosecond(); + const int64_t time2 = + ts_value2.time_part_to_seconds() * TimeStampNsValue::NANOS_PER_SECOND + + ts_value2.nanosecond(); + if (day > 0) { + day -= time2 < time1; + } else if (day < 0) { + day += time2 > time1; + } + return UNIT == WEEK ? day / 7 : day; + } else { + constexpr int64_t divisor = UNIT == HOUR ? 3600 * TimeStampNsValue::NANOS_PER_SECOND + : UNIT == MINUTE ? 60 * TimeStampNsValue::NANOS_PER_SECOND + : UNIT == SECOND ? TimeStampNsValue::NANOS_PER_SECOND + : UNIT == MILLISECOND ? TimeStampNsValue::NANOS_PER_MILLISECOND + : TimeStampNsValue::NANOS_PER_MICROSECOND; + static_assert(UNIT == HOUR || UNIT == MINUTE || UNIT == SECOND || UNIT == MILLISECOND || + UNIT == MICROSECOND, + "Unsupported TimeUnit for TIMESTAMP_NS datetime_diff"); + return static_cast( + (static_cast<__int128>(ts_value2.epoch_nanos()) - ts_value1.epoch_nanos()) / + divisor); + } +} + +} // namespace doris + +template <> +struct std::hash { + size_t operator()(const doris::TimeStampNsValue& value) const { + return std::hash {}(value.epoch_nanos()); + } +}; diff --git a/be/src/exec/common/field_visitors.h b/be/src/exec/common/field_visitors.h index 8b14b6bbd17626..25ca811dd889ae 100644 --- a/be/src/exec/common/field_visitors.h +++ b/be/src/exec/common/field_visitors.h @@ -47,6 +47,9 @@ typename std::decay_t::ResultType apply_visitor(Visitor&& visitor, F&& case PrimitiveType::TYPE_DATETIMEV2: return visitor.template apply( field.template get()); + case PrimitiveType::TYPE_TIMESTAMP_NS: + return visitor.template apply( + field.template get()); case PrimitiveType::TYPE_TIMESTAMPTZ: return visitor.template apply( field.template get()); diff --git a/be/src/exec/common/hash_table/hash.h b/be/src/exec/common/hash_table/hash.h index e8487bf4c8db96..ea598fd7fc383a 100644 --- a/be/src/exec/common/hash_table/hash.h +++ b/be/src/exec/common/hash_table/hash.h @@ -26,6 +26,7 @@ #include "core/string_ref.h" #include "core/types.h" #include "core/uint128.h" +#include "core/value/timestamp_ns_value.h" #include "parallel_hashmap/phmap_utils.h" // Here is an empirical value. @@ -111,6 +112,11 @@ struct DefaultHash> { } }; +template <> +struct DefaultHash { + size_t operator()(doris::TimeStampNsValue key) const { return int_hash64(key.epoch_nanos()); } +}; + template <> struct DefaultHash { size_t operator()(doris::TimestampTzValue key) const { @@ -168,6 +174,11 @@ inline size_t hash_crc32(doris::DateV2Value u) { return hash_crc32(u.to_date_int_val()); } +template <> +inline size_t hash_crc32(doris::TimeStampNsValue u) { + return hash_crc32(u.epoch_nanos()); +} + template <> inline size_t hash_crc32(doris::TimestampTzValue u) { return hash_crc32(u.to_date_int_val()); @@ -196,6 +207,7 @@ DEFINE_HASH(doris::Float64) DEFINE_HASH(doris::VecDateTimeValue) DEFINE_HASH(doris::DateV2Value) DEFINE_HASH(doris::DateV2Value) +DEFINE_HASH(doris::TimeStampNsValue) DEFINE_HASH(doris::TimestampTzValue) DEFINE_HASH(unsigned __int128) diff --git a/be/src/exec/common/variant_util.cpp b/be/src/exec/common/variant_util.cpp index a208bfb743248a..7bcf108123c0d4 100644 --- a/be/src/exec/common/variant_util.cpp +++ b/be/src/exec/common/variant_util.cpp @@ -531,7 +531,8 @@ void get_column_by_type(const DataTypePtr& data_type, const std::string& name, T PrimitiveType type = data_type->get_primitive_type(); if (is_int_or_bool(type) || is_string_type(type) || is_float_or_double(type) || is_ip(type) || - is_date_or_datetime(type) || type == PrimitiveType::TYPE_DATEV2) { + is_date_or_datetime(type) || type == PrimitiveType::TYPE_DATEV2 || + type == PrimitiveType::TYPE_TIMESTAMP_NS) { column.set_length(cast_set(data_type->get_size_of_value_in_memory())); return; } @@ -722,6 +723,7 @@ bool is_bf_supported_by_fe_for_variant_subcolumn(FieldType type) { case FieldType::OLAP_FIELD_TYPE_DATETIME: case FieldType::OLAP_FIELD_TYPE_DATEV2: case FieldType::OLAP_FIELD_TYPE_DATETIMEV2: + case FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS: case FieldType::OLAP_FIELD_TYPE_TIMESTAMPTZ: case FieldType::OLAP_FIELD_TYPE_DECIMAL: case FieldType::OLAP_FIELD_TYPE_DECIMAL32: diff --git a/be/src/exec/operator/scan_operator.cpp b/be/src/exec/operator/scan_operator.cpp index 0d51c2e3bfd1b6..8707c064f10e17 100644 --- a/be/src/exec/operator/scan_operator.cpp +++ b/be/src/exec/operator/scan_operator.cpp @@ -933,12 +933,13 @@ Status ScanLocalStateBase::_change_value_range(bool is_equal_op, func(temp_range, to_olap_filter_type(fn_name), tmp_value); } } else if constexpr ((PrimitiveType == TYPE_DECIMALV2) || (PrimitiveType == TYPE_DATETIMEV2) || - (PrimitiveType == TYPE_TINYINT) || (PrimitiveType == TYPE_SMALLINT) || - (PrimitiveType == TYPE_INT) || (PrimitiveType == TYPE_BIGINT) || - (PrimitiveType == TYPE_LARGEINT) || (PrimitiveType == TYPE_FLOAT) || - (PrimitiveType == TYPE_DOUBLE) || (PrimitiveType == TYPE_IPV4) || - (PrimitiveType == TYPE_IPV6) || (PrimitiveType == TYPE_DECIMAL32) || - (PrimitiveType == TYPE_DECIMAL64) || (PrimitiveType == TYPE_DECIMAL128I) || + (PrimitiveType == TYPE_TIMESTAMP_NS) || (PrimitiveType == TYPE_TINYINT) || + (PrimitiveType == TYPE_SMALLINT) || (PrimitiveType == TYPE_INT) || + (PrimitiveType == TYPE_BIGINT) || (PrimitiveType == TYPE_LARGEINT) || + (PrimitiveType == TYPE_FLOAT) || (PrimitiveType == TYPE_DOUBLE) || + (PrimitiveType == TYPE_IPV4) || (PrimitiveType == TYPE_IPV6) || + (PrimitiveType == TYPE_DECIMAL32) || (PrimitiveType == TYPE_DECIMAL64) || + (PrimitiveType == TYPE_DECIMAL128I) || (PrimitiveType == TYPE_DECIMAL256) || (PrimitiveType == TYPE_BOOLEAN) || (PrimitiveType == TYPE_DATEV2) || (PrimitiveType == TYPE_TIMESTAMPTZ) || (PrimitiveType == TYPE_DATETIME) || is_string_type(PrimitiveType)) { diff --git a/be/src/exec/runtime_filter/runtime_filter_partition_pruner.cpp b/be/src/exec/runtime_filter/runtime_filter_partition_pruner.cpp index 6e6d43472c526a..c11c08a0ffd31f 100644 --- a/be/src/exec/runtime_filter/runtime_filter_partition_pruner.cpp +++ b/be/src/exec/runtime_filter/runtime_filter_partition_pruner.cpp @@ -208,6 +208,7 @@ Status ParsedPartitionBoundaries::parse( BUILD_BOUNDARY_CVR(DATETIME) BUILD_BOUNDARY_CVR(DATEV2) BUILD_BOUNDARY_CVR(DATETIMEV2) + BUILD_BOUNDARY_CVR(TIMESTAMP_NS) BUILD_BOUNDARY_CVR(TIMESTAMPTZ) BUILD_BOUNDARY_CVR(VARCHAR) BUILD_BOUNDARY_CVR(STRING) diff --git a/be/src/exec/runtime_filter/runtime_filter_wrapper.cpp b/be/src/exec/runtime_filter/runtime_filter_wrapper.cpp index 109fa6f0171878..d8f108c3ec07b1 100644 --- a/be/src/exec/runtime_filter/runtime_filter_wrapper.cpp +++ b/be/src/exec/runtime_filter/runtime_filter_wrapper.cpp @@ -298,6 +298,8 @@ Status RuntimeFilterWrapper::_assign(const PInFilter& in_filter, bool contain_nu } case TYPE_TIMESTAMPTZ: [[fallthrough]]; + case TYPE_TIMESTAMP_NS: + [[fallthrough]]; case TYPE_DATETIMEV2: { batch_assign(in_filter, [](std::shared_ptr& set, PColumnValue& column) { auto date_v2_val = column.longval(); @@ -491,6 +493,8 @@ Status RuntimeFilterWrapper::_assign(const PMinMaxFilter& minmax_filter, bool co } case TYPE_TIMESTAMPTZ: [[fallthrough]]; + case TYPE_TIMESTAMP_NS: + [[fallthrough]]; case TYPE_DATETIMEV2: { int64_t min_val = minmax_filter.min_val().longval(); int64_t max_val = minmax_filter.max_val().longval(); diff --git a/be/src/exec/runtime_filter/utils.h b/be/src/exec/runtime_filter/utils.h index aa43950b2f0ace..515a5fe7382cd7 100644 --- a/be/src/exec/runtime_filter/utils.h +++ b/be/src/exec/runtime_filter/utils.h @@ -25,6 +25,7 @@ #include "core/extended_types.h" #include "core/types.h" #include "core/value/large_int_value.h" +#include "core/value/timestamp_ns_value.h" #include "core/value/timestamptz_value.h" #include "exec/runtime_filter/runtime_filter_definitions.h" #include "exprs/vexpr_fwd.h" @@ -75,6 +76,8 @@ auto get_convertor() { return [](PColumnValue* value, const T& data) { value->set_longval(data.to_date_int_val()); }; + } else if constexpr (std::is_same_v) { + return [](PColumnValue* value, const T& data) { value->set_longval(data.epoch_nanos()); }; } else { throw Exception(ErrorCode::INTERNAL_ERROR, "runtime filter data convertor meet invalid type {}", typeid(T).name()); diff --git a/be/src/exec/sink/writer/iceberg/partition_transformers.cpp b/be/src/exec/sink/writer/iceberg/partition_transformers.cpp index e38e0e4c5eb8a7..87523a91ae5b51 100644 --- a/be/src/exec/sink/writer/iceberg/partition_transformers.cpp +++ b/be/src/exec/sink/writer/iceberg/partition_transformers.cpp @@ -43,9 +43,12 @@ std::string floating_point_partition_value_to_string(T value) { const std::chrono::sys_days PartitionColumnTransformUtils::EPOCH = std::chrono::sys_days( std::chrono::year {1970} / std::chrono::January / std::chrono::day {1}); +// Keep the complete Iceberg transform/type dispatch in one factory so unsupported combinations +// consistently return the same error. +// NOLINTNEXTLINE(readability-function-size) std::unique_ptr PartitionColumnTransforms::create( const doris::iceberg::PartitionField& field, const DataTypePtr& source_type) { - auto& transform = field.transform(); + const auto& transform = field.transform(); static const std::regex has_width(R"((\w+)\[(\d+)\])"); std::smatch width_match; @@ -115,7 +118,8 @@ std::unique_ptr PartitionColumnTransforms::create( return std::make_unique(source_type, parsed_width); } - case TYPE_DATETIMEV2: { + case TYPE_DATETIMEV2: + case TYPE_TIMESTAMP_NS: { return std::make_unique(source_type, parsed_width); } @@ -155,7 +159,8 @@ std::unique_ptr PartitionColumnTransforms::create( case TYPE_DATEV2: { return std::make_unique(source_type); } - case TYPE_DATETIMEV2: { + case TYPE_DATETIMEV2: + case TYPE_TIMESTAMP_NS: { return std::make_unique(source_type); } default: { @@ -169,7 +174,8 @@ std::unique_ptr PartitionColumnTransforms::create( case TYPE_DATEV2: { return std::make_unique(source_type); } - case TYPE_DATETIMEV2: { + case TYPE_DATETIMEV2: + case TYPE_TIMESTAMP_NS: { return std::make_unique(source_type); } default: { @@ -183,7 +189,8 @@ std::unique_ptr PartitionColumnTransforms::create( case TYPE_DATEV2: { return std::make_unique(source_type); } - case TYPE_DATETIMEV2: { + case TYPE_DATETIMEV2: + case TYPE_TIMESTAMP_NS: { return std::make_unique(source_type); } default: { @@ -194,7 +201,8 @@ std::unique_ptr PartitionColumnTransforms::create( } } else if (transform == "hour") { switch (source_type->get_primitive_type()) { - case TYPE_DATETIMEV2: { + case TYPE_DATETIMEV2: + case TYPE_TIMESTAMP_NS: { return std::make_unique(source_type); } default: { @@ -272,6 +280,9 @@ std::string PartitionColumnTransform::get_partition_value(const DataTypePtr type buf, type->get_scale()); return std::string(buf, pos - buf - 1); } + case TYPE_TIMESTAMP_NS: { + return std::any_cast(value).to_string(); + } case TYPE_DECIMALV2: { return std::any_cast(value).to_string(type->get_scale()); } diff --git a/be/src/exec/sink/writer/iceberg/partition_transformers.h b/be/src/exec/sink/writer/iceberg/partition_transformers.h index 51bca7000ad5bb..9de9a070845bce 100644 --- a/be/src/exec/sink/writer/iceberg/partition_transformers.h +++ b/be/src/exec/sink/writer/iceberg/partition_transformers.h @@ -20,6 +20,7 @@ #include "core/column/column.h" #include "core/column/column_nullable.h" #include "core/data_type/data_type_factory.hpp" +#include "core/value/timestamp_ns_value.h" #include "exec/common/stringop_substring.h" #include "exprs/function/cast/cast_to_datetimev2_impl.hpp" #include "exprs/function/cast/cast_to_datev2_impl.hpp" @@ -70,6 +71,29 @@ class PartitionColumnTransformUtils { return epoch_datetime; } + static DateV2Value timestamp_value_at(const IColumn& column, size_t row, + PrimitiveType source_type) { + if (source_type == TYPE_TIMESTAMP_NS) { + return assert_cast(column).get_data()[row].to_datetime(); + } + DORIS_CHECK(source_type == TYPE_DATETIMEV2); + return assert_cast(column).get_data()[row]; + } + + static int64_t timestamp_bucket_value_at(const IColumn& column, size_t row, + PrimitiveType source_type) { + if (source_type == TYPE_TIMESTAMP_NS) { + return assert_cast(column).get_data()[row].epoch_nanos(); + } + auto value = timestamp_value_at(column, row, source_type); + int64_t timestamp = 0; + if (!value.unix_timestamp(×tamp, "UTC")) { + LOG(WARNING) << "Failed to call unix_timestamp: " << value.debug_string(); + return 0; + } + return timestamp * 1'000'000; + } + static std::string human_year(int year_ordinal) { auto ymd = std::chrono::year_month_day {EPOCH} + std::chrono::years(year_ordinal); return std::to_string(static_cast(ymd.year())); @@ -666,32 +690,19 @@ class TimestampBucketPartitionColumnTransform : public PartitionColumnTransform null_map_column_ptr = nullable_column->get_null_map_column_ptr(); column_ptr = nullable_column->get_nested_column_ptr(); } - const auto& in_data = assert_cast(column_ptr.get())->get_data(); + PrimitiveType source_type = + remove_nullable(column_with_type_and_name.type)->get_primitive_type(); //3) do partition routing auto col_res = ColumnInt32::create(); ColumnInt32::Container& out_data = col_res->get_data(); - out_data.resize(in_data.size()); - const auto* end_in = in_data.data() + in_data.size(); + out_data.resize(column_ptr->size()); - const auto* __restrict p_in = in_data.data(); - auto* __restrict p_out = out_data.data(); - - while (p_in < end_in) { - DateV2Value value = - binary_cast>(*(UInt64*)p_in); - - int64_t timestamp; - if (!value.unix_timestamp(×tamp, "UTC")) { - LOG(WARNING) << "Failed to call unix_timestamp :" << value.debug_string(); - timestamp = 0; - } - Int64 long_value = static_cast(timestamp) * 1000000; + for (size_t row = 0; row < column_ptr->size(); ++row) { + Int64 long_value = PartitionColumnTransformUtils::timestamp_bucket_value_at( + *column_ptr, row, source_type); uint32_t hash_value = HashUtil::murmur_hash3_32(&long_value, sizeof(long_value), 0); - - *p_out = (hash_value & INT32_MAX) % _bucket_num; - ++p_in; - ++p_out; + out_data[row] = (hash_value & INT32_MAX) % _bucket_num; } //4) create the partition column and return @@ -875,25 +886,20 @@ class TimestampYearPartitionColumnTransform : public PartitionColumnTransform { null_map_column_ptr = nullable_column->get_null_map_column_ptr(); column_ptr = nullable_column->get_nested_column_ptr(); } - const auto& in_data = assert_cast(column_ptr.get())->get_data(); + PrimitiveType source_type = + remove_nullable(column_with_type_and_name.type)->get_primitive_type(); //3) do partition routing auto col_res = ColumnInt32::create(); ColumnInt32::Container& out_data = col_res->get_data(); - out_data.resize(in_data.size()); + out_data.resize(column_ptr->size()); - const auto* end_in = in_data.data() + in_data.size(); - const auto* __restrict p_in = in_data.data(); - auto* __restrict p_out = out_data.data(); - - while (p_in < end_in) { - DateV2Value value = - binary_cast>(*(UInt64*)p_in); + for (size_t row = 0; row < column_ptr->size(); ++row) { + auto value = PartitionColumnTransformUtils::timestamp_value_at(*column_ptr, row, + source_type); // datetime_diff actually returns int - *p_out = cast_set( + out_data[row] = cast_set( datetime_diff(PartitionColumnTransformUtils::epoch_datetime(), value)); - ++p_in; - ++p_out; } //4) create the partition column and return @@ -1013,25 +1019,20 @@ class TimestampMonthPartitionColumnTransform : public PartitionColumnTransform { null_map_column_ptr = nullable_column->get_null_map_column_ptr(); column_ptr = nullable_column->get_nested_column_ptr(); } - const auto& in_data = assert_cast(column_ptr.get())->get_data(); + PrimitiveType source_type = + remove_nullable(column_with_type_and_name.type)->get_primitive_type(); //3) do partition routing auto col_res = ColumnInt32::create(); ColumnInt32::Container& out_data = col_res->get_data(); - out_data.resize(in_data.size()); + out_data.resize(column_ptr->size()); - const auto* end_in = in_data.data() + in_data.size(); - const auto* __restrict p_in = in_data.data(); - auto* __restrict p_out = out_data.data(); - - while (p_in < end_in) { - DateV2Value value = - binary_cast>(*(UInt64*)p_in); + for (size_t row = 0; row < column_ptr->size(); ++row) { + auto value = PartitionColumnTransformUtils::timestamp_value_at(*column_ptr, row, + source_type); // datetime_diff actually returns int - *p_out = cast_set( + out_data[row] = cast_set( datetime_diff(PartitionColumnTransformUtils::epoch_datetime(), value)); - ++p_in; - ++p_out; } //4) create the partition column and return @@ -1156,25 +1157,20 @@ class TimestampDayPartitionColumnTransform : public PartitionColumnTransform { null_map_column_ptr = nullable_column->get_null_map_column_ptr(); column_ptr = nullable_column->get_nested_column_ptr(); } - const auto& in_data = assert_cast(column_ptr.get())->get_data(); + PrimitiveType source_type = + remove_nullable(column_with_type_and_name.type)->get_primitive_type(); //3) do partition routing auto col_res = ColumnInt32::create(); ColumnInt32::Container& out_data = col_res->get_data(); - out_data.resize(in_data.size()); - - const auto* end_in = in_data.data() + in_data.size(); - const auto* __restrict p_in = in_data.data(); - auto* __restrict p_out = out_data.data(); + out_data.resize(column_ptr->size()); - while (p_in < end_in) { - DateV2Value value = - binary_cast>(*(UInt64*)p_in); + for (size_t row = 0; row < column_ptr->size(); ++row) { + auto value = PartitionColumnTransformUtils::timestamp_value_at(*column_ptr, row, + source_type); // datetime_diff actually returns int - *p_out = cast_set( + out_data[row] = cast_set( datetime_diff(PartitionColumnTransformUtils::epoch_datetime(), value)); - ++p_in; - ++p_out; } //4) create the partition column and return @@ -1229,25 +1225,20 @@ class TimestampHourPartitionColumnTransform : public PartitionColumnTransform { null_map_column_ptr = nullable_column->get_null_map_column_ptr(); column_ptr = nullable_column->get_nested_column_ptr(); } - const auto& in_data = assert_cast(column_ptr.get())->get_data(); + PrimitiveType source_type = + remove_nullable(column_with_type_and_name.type)->get_primitive_type(); //3) do partition routing auto col_res = ColumnInt32::create(); ColumnInt32::Container& out_data = col_res->get_data(); - out_data.resize(in_data.size()); + out_data.resize(column_ptr->size()); - const auto* end_in = in_data.data() + in_data.size(); - const auto* __restrict p_in = in_data.data(); - auto* __restrict p_out = out_data.data(); - - while (p_in < end_in) { - DateV2Value value = - binary_cast>(*(UInt64*)p_in); + for (size_t row = 0; row < column_ptr->size(); ++row) { + auto value = PartitionColumnTransformUtils::timestamp_value_at(*column_ptr, row, + source_type); // hour diff would't overflow int32 - *p_out = cast_set( + out_data[row] = cast_set( datetime_diff(PartitionColumnTransformUtils::epoch_datetime(), value)); - ++p_in; - ++p_out; } //4) create the partition column and return diff --git a/be/src/exec/sink/writer/iceberg/viceberg_table_writer.cpp b/be/src/exec/sink/writer/iceberg/viceberg_table_writer.cpp index 5b7c31d6c0d9cb..03048fd03c3055 100644 --- a/be/src/exec/sink/writer/iceberg/viceberg_table_writer.cpp +++ b/be/src/exec/sink/writer/iceberg/viceberg_table_writer.cpp @@ -843,6 +843,9 @@ std::any VIcebergTableWriter::_get_iceberg_partition_value( case TYPE_DATETIMEV2: { return binary_cast>(*(int64_t*)item); } + case TYPE_TIMESTAMP_NS: { + return TimeStampNsValue(*reinterpret_cast(item)); + } case TYPE_DECIMALV2: { return *(Decimal128V2*)(item); } diff --git a/be/src/exprs/aggregate/aggregate_function_approx_count_distinct.cpp b/be/src/exprs/aggregate/aggregate_function_approx_count_distinct.cpp index 28aa90fc4420d2..2821382ebeb4e2 100644 --- a/be/src/exprs/aggregate/aggregate_function_approx_count_distinct.cpp +++ b/be/src/exprs/aggregate/aggregate_function_approx_count_distinct.cpp @@ -30,7 +30,7 @@ AggregateFunctionPtr create_aggregate_function_approx_count_distinct( TYPE_BOOLEAN, TYPE_TINYINT, TYPE_SMALLINT, TYPE_INT, TYPE_BIGINT, TYPE_LARGEINT, TYPE_FLOAT, TYPE_DOUBLE, TYPE_DECIMALV2, TYPE_DECIMAL32, TYPE_DECIMAL64, TYPE_DECIMAL128I, TYPE_DECIMAL256, TYPE_VARCHAR, TYPE_DATEV2, TYPE_DATETIMEV2, - TYPE_IPV4, TYPE_IPV6, + TYPE_TIMESTAMP_NS, TYPE_IPV4, TYPE_IPV6, TYPE_TIMESTAMPTZ>::create(argument_types, result_is_nullable, attr); diff --git a/be/src/exprs/aggregate/aggregate_function_approx_count_distinct.h b/be/src/exprs/aggregate/aggregate_function_approx_count_distinct.h index cce63de9b25580..d0330e29212c94 100644 --- a/be/src/exprs/aggregate/aggregate_function_approx_count_distinct.h +++ b/be/src/exprs/aggregate/aggregate_function_approx_count_distinct.h @@ -95,7 +95,8 @@ class AggregateFunctionApproxCountDistinct final void add(AggregateDataPtr __restrict place, const IColumn** columns, ssize_t row_num, Arena&) const override { if constexpr (is_decimal(type) || is_int_or_bool(type) || is_ip(type) || - is_date_type(type) || is_timestamptz_type(type) || is_float_or_double(type) || + is_date_type(type) || is_timestamp_ns_type(type) || + is_timestamptz_type(type) || is_float_or_double(type) || type == TYPE_TIMEV2) { auto column = assert_cast(columns[0]); diff --git a/be/src/exprs/aggregate/aggregate_function_array_agg.h b/be/src/exprs/aggregate/aggregate_function_array_agg.h index 002e11cdd13d5f..5bf6d6fbee04de 100644 --- a/be/src/exprs/aggregate/aggregate_function_array_agg.h +++ b/be/src/exprs/aggregate/aggregate_function_array_agg.h @@ -231,7 +231,7 @@ struct AggregateFunctionArrayAggData { template requires(!is_string_type(T) && !is_int_or_bool(T) && !is_float_or_double(T) && !is_decimal(T) && - !is_date_type(T) && !is_ip(T)) + !is_date_type(T) && !is_timestamp_ns_type(T) && !is_ip(T)) struct AggregateFunctionArrayAggData { static constexpr PrimitiveType PType = T; static constexpr bool use_native_serde = true; @@ -410,7 +410,8 @@ class AggregateFunctionArrayAgg final vec.insert_from(vec_src, i); } else if constexpr (!is_string_type(Data::PType) && !is_int_or_bool(Data::PType) && !is_float_or_double(Data::PType) && !is_decimal(Data::PType) && - !is_date_type(Data::PType) && !is_ip(Data::PType)) { + !is_date_type(Data::PType) && !is_timestamp_ns_type(Data::PType) && + !is_ip(Data::PType)) { auto& vec = col_null->get_nested_column(); vec.insert_from(col_src.get_nested_column(), i); } else { diff --git a/be/src/exprs/aggregate/aggregate_function_collect.h b/be/src/exprs/aggregate/aggregate_function_collect.h index 96c9ab96cb5a23..52894f5e05c2f9 100644 --- a/be/src/exprs/aggregate/aggregate_function_collect.h +++ b/be/src/exprs/aggregate/aggregate_function_collect.h @@ -306,7 +306,7 @@ struct AggregateFunctionCollectListData { template requires(!is_string_type(T) && !is_int_or_bool(T) && !is_float_or_double(T) && !is_decimal(T) && - !is_date_type(T) && !is_ip(T) && !is_timestamptz_type(T)) + !is_date_type(T) && !is_timestamp_ns_type(T) && !is_ip(T) && !is_timestamptz_type(T)) struct AggregateFunctionCollectListData { static constexpr PrimitiveType PType = T; using ElementType = StringRef; diff --git a/be/src/exprs/aggregate/aggregate_function_histogram.cpp b/be/src/exprs/aggregate/aggregate_function_histogram.cpp index 622359b3da2199..17cc1cc96ca77d 100644 --- a/be/src/exprs/aggregate/aggregate_function_histogram.cpp +++ b/be/src/exprs/aggregate/aggregate_function_histogram.cpp @@ -39,11 +39,11 @@ AggregateFunctionPtr create_aggregate_function_histogram(const std::string& name const bool result_is_nullable, const AggregateFunctionAttr& attr) { assert_arity_range(name, argument_types, 1, 2); - using creator = - creator_with_type_list; + using creator = creator_with_type_list; if (argument_types.size() == 2) { return creator::create( argument_types, result_is_nullable, attr); @@ -58,4 +58,4 @@ void register_aggregate_function_histogram(AggregateFunctionSimpleFactory& facto factory.register_alias("histogram", "hist"); } -} // namespace doris \ No newline at end of file +} // namespace doris diff --git a/be/src/exprs/aggregate/aggregate_function_map_v2.cpp b/be/src/exprs/aggregate/aggregate_function_map_v2.cpp index eaaec268914488..28f6f020ab0afd 100644 --- a/be/src/exprs/aggregate/aggregate_function_map_v2.cpp +++ b/be/src/exprs/aggregate/aggregate_function_map_v2.cpp @@ -53,6 +53,7 @@ AggregateFunctionPtr create_aggregate_function_map_agg_v2(const std::string& nam case PrimitiveType::TYPE_VARCHAR: case PrimitiveType::TYPE_DATEV2: case PrimitiveType::TYPE_DATETIMEV2: + case PrimitiveType::TYPE_TIMESTAMP_NS: case PrimitiveType::TYPE_TIMEV2: case PrimitiveType::TYPE_TIMESTAMPTZ: return create_agg_function_map_agg_v2(argument_types, result_is_nullable, attr); @@ -67,4 +68,4 @@ void register_aggregate_function_map_agg_v2(AggregateFunctionSimpleFactory& fact factory.register_function_both("map_agg_v2", create_aggregate_function_map_agg_v2); } -} // namespace doris \ No newline at end of file +} // namespace doris diff --git a/be/src/exprs/aggregate/aggregate_function_min_max_by.cpp b/be/src/exprs/aggregate/aggregate_function_min_max_by.cpp index c8f25f56ee3e68..70e5508069e9ea 100644 --- a/be/src/exprs/aggregate/aggregate_function_min_max_by.cpp +++ b/be/src/exprs/aggregate/aggregate_function_min_max_by.cpp @@ -34,6 +34,10 @@ std::unique_ptr create_max_min_value(const DataTypePtr& type, i } return true; }; + if (type->get_primitive_type() == TYPE_TIMESTAMP_NS) { + call(DispatchDataType()); + return result; + } if (dispatch_switch_scalar(type->get_primitive_type(), call)) { return result; } diff --git a/be/src/exprs/aggregate/aggregate_function_min_max_by.h b/be/src/exprs/aggregate/aggregate_function_min_max_by.h index d6cbb3645ce0ba..dfba3fbcd25038 100644 --- a/be/src/exprs/aggregate/aggregate_function_min_max_by.h +++ b/be/src/exprs/aggregate/aggregate_function_min_max_by.h @@ -337,6 +337,12 @@ AggregateFunctionPtr create_aggregate_function_min_max_by(const String& name, } return true; }; + // Keep nano dispatch local because the shared scalar dispatcher is also used by templates + // that assume arithmetic support. + if (argument_types[1]->get_primitive_type() == TYPE_TIMESTAMP_NS) { + call(DispatchDataType()); + return result; + } if (dispatch_switch_scalar(argument_types[1]->get_primitive_type(), call)) { return result; } diff --git a/be/src/exprs/aggregate/aggregate_function_min_max_impl.h b/be/src/exprs/aggregate/aggregate_function_min_max_impl.h index 75a03f8893b53a..9717cc0461c7c1 100644 --- a/be/src/exprs/aggregate/aggregate_function_min_max_impl.h +++ b/be/src/exprs/aggregate/aggregate_function_min_max_impl.h @@ -59,6 +59,10 @@ AggregateFunctionPtr create_aggregate_function_single_value(const String& name, return creator_without_type::create_unary_arguments< AggregateFunctionsSingleValue>>>( argument_types, result_is_nullable, attr); + case PrimitiveType::TYPE_TIMESTAMP_NS: + return creator_without_type::create_unary_arguments< + AggregateFunctionsSingleValue>>>( + argument_types, result_is_nullable, attr); case PrimitiveType::TYPE_TIMESTAMPTZ: return creator_without_type::create_unary_arguments< AggregateFunctionsSingleValue>>>( diff --git a/be/src/exprs/aggregate/aggregate_function_sequence_match.cpp b/be/src/exprs/aggregate/aggregate_function_sequence_match.cpp index 7e55c11e2219c3..3de5d44fcc091b 100644 --- a/be/src/exprs/aggregate/aggregate_function_sequence_match.cpp +++ b/be/src/exprs/aggregate/aggregate_function_sequence_match.cpp @@ -48,6 +48,9 @@ AggregateFunctionPtr create_aggregate_function_sequence_base(const std::string& case TYPE_DATETIMEV2: return creator_without_type::create>( argument_types, result_is_nullable, attr); + case TYPE_TIMESTAMP_NS: + return creator_without_type::create>( + argument_types, result_is_nullable, attr); case TYPE_DATEV2: return creator_without_type::create>( argument_types, result_is_nullable, attr); diff --git a/be/src/exprs/aggregate/aggregate_function_topn_array.cpp b/be/src/exprs/aggregate/aggregate_function_topn_array.cpp index 8c8fee3f4fde9d..7f1ebf7b4c2e5d 100644 --- a/be/src/exprs/aggregate/aggregate_function_topn_array.cpp +++ b/be/src/exprs/aggregate/aggregate_function_topn_array.cpp @@ -27,11 +27,10 @@ using ImplArray = AggregateFunctionTopNImplArray; template using ImplArrayWithDefault = AggregateFunctionTopNImplArray; -using topn_array_creator = - creator_with_type_list; +using topn_array_creator = creator_with_type_list< + TYPE_TINYINT, TYPE_SMALLINT, TYPE_INT, TYPE_BIGINT, TYPE_LARGEINT, TYPE_FLOAT, TYPE_DOUBLE, + TYPE_DECIMAL32, TYPE_DECIMAL64, TYPE_DECIMAL128I, TYPE_DECIMAL256, TYPE_VARCHAR, + TYPE_DATEV2, TYPE_DATETIMEV2, TYPE_TIMESTAMP_NS, TYPE_TIMESTAMPTZ, TYPE_IPV4, TYPE_IPV6>; AggregateFunctionPtr create_aggregate_function_topn_array(const std::string& name, const DataTypes& argument_types, diff --git a/be/src/exprs/aggregate/aggregate_function_topn_weighted.cpp b/be/src/exprs/aggregate/aggregate_function_topn_weighted.cpp index d1c8102458443c..dc955320d32ff5 100644 --- a/be/src/exprs/aggregate/aggregate_function_topn_weighted.cpp +++ b/be/src/exprs/aggregate/aggregate_function_topn_weighted.cpp @@ -27,11 +27,10 @@ using ImplWeight = AggregateFunctionTopNImplWeight; template using ImplWeightWithDefault = AggregateFunctionTopNImplWeight; -using topn_weighted_creator = - creator_with_type_list; +using topn_weighted_creator = creator_with_type_list< + TYPE_TINYINT, TYPE_SMALLINT, TYPE_INT, TYPE_BIGINT, TYPE_LARGEINT, TYPE_FLOAT, TYPE_DOUBLE, + TYPE_DECIMAL32, TYPE_DECIMAL64, TYPE_DECIMAL128I, TYPE_DECIMAL256, TYPE_VARCHAR, + TYPE_DATEV2, TYPE_DATETIMEV2, TYPE_TIMESTAMP_NS, TYPE_TIMESTAMPTZ, TYPE_IPV4, TYPE_IPV6>; AggregateFunctionPtr create_aggregate_function_topn_weighted(const std::string& name, const DataTypes& argument_types, diff --git a/be/src/exprs/aggregate/aggregate_function_uniq.cpp b/be/src/exprs/aggregate/aggregate_function_uniq.cpp index 9bfcc38855c46e..f9f5d75de774bc 100644 --- a/be/src/exprs/aggregate/aggregate_function_uniq.cpp +++ b/be/src/exprs/aggregate/aggregate_function_uniq.cpp @@ -52,12 +52,13 @@ AggregateFunctionPtr create_aggregate_function_uniq(const std::string& name, argument_types, result_is_nullable, attr); } } - return creator_with_type_list< - TYPE_BOOLEAN, TYPE_TINYINT, TYPE_SMALLINT, TYPE_INT, TYPE_BIGINT, TYPE_LARGEINT, - TYPE_DECIMAL32, TYPE_DECIMAL64, TYPE_DECIMAL128I, TYPE_DECIMAL256, TYPE_VARCHAR, - TYPE_ARRAY, TYPE_FLOAT, TYPE_DOUBLE, TYPE_DATEV2, TYPE_DATETIMEV2, TYPE_TIMESTAMPTZ, - TYPE_VARBINARY>::create(argument_types, result_is_nullable, - attr); + return creator_with_type_list::create( + argument_types, result_is_nullable, attr); } void register_aggregate_function_uniq(AggregateFunctionSimpleFactory& factory) { diff --git a/be/src/exprs/aggregate/aggregate_function_window_funnel.cpp b/be/src/exprs/aggregate/aggregate_function_window_funnel.cpp index 3c1a35e1e06f85..060afb7379cef6 100644 --- a/be/src/exprs/aggregate/aggregate_function_window_funnel.cpp +++ b/be/src/exprs/aggregate/aggregate_function_window_funnel.cpp @@ -39,6 +39,9 @@ AggregateFunctionPtr create_aggregate_function_window_funnel(const std::string& if (argument_types[2]->get_primitive_type() == TYPE_DATETIMEV2) { return creator_without_type::create>( argument_types, result_is_nullable, attr); + } else if (argument_types[2]->get_primitive_type() == TYPE_TIMESTAMP_NS) { + return creator_without_type::create>( + argument_types, result_is_nullable, attr); } else if (argument_types[2]->get_primitive_type() == TYPE_TIMESTAMPTZ) { return creator_without_type::create>( argument_types, result_is_nullable, attr); diff --git a/be/src/exprs/aggregate/aggregate_function_window_funnel.h b/be/src/exprs/aggregate/aggregate_function_window_funnel.h index 646d8b581bc735..2ecacd5b083715 100644 --- a/be/src/exprs/aggregate/aggregate_function_window_funnel.h +++ b/be/src/exprs/aggregate/aggregate_function_window_funnel.h @@ -160,6 +160,18 @@ struct WindowFunnelState { } } + bool _within_window(const DateValueType& base_timestamp, const DateValueType& current_timestamp, + const DateValueType& end_timestamp) const { + if constexpr (T == TYPE_TIMESTAMP_NS) { + const auto elapsed_nanos = static_cast<__int128>(current_timestamp.epoch_nanos()) - + base_timestamp.epoch_nanos(); + const auto window_nanos = + static_cast<__int128>(window) * TimeStampNsValue::NANOS_PER_SECOND; + return elapsed_nanos <= window_nanos; + } + return current_timestamp <= end_timestamp; + } + template int _match_event_list(size_t& start_row, size_t row_count) const { int matched_count = 0; @@ -170,7 +182,6 @@ struct WindowFunnelState { "the sliding time window must be a positive integer, but got: {}", window); } - TimeInterval interval(SECOND, window, false); int column_idx = 0; const auto& timestamp_data = events_list.dt; const auto& first_event_data = events_list.event_columns_data[column_idx].data(); @@ -178,8 +189,12 @@ struct WindowFunnelState { start_row = match_row + 1; if (match_row < row_count) { auto prev_timestamp = timestamp_data[match_row]; - end_timestamp = prev_timestamp; - end_timestamp.template date_add_interval(interval); + const auto first_timestamp = prev_timestamp; + if constexpr (T != TYPE_TIMESTAMP_NS) { + TimeInterval interval(SECOND, window, false); + end_timestamp = first_timestamp; + end_timestamp.template date_add_interval(interval); + } matched_count++; column_idx++; @@ -190,7 +205,7 @@ struct WindowFunnelState { if constexpr (WINDOW_FUNNEL_MODE == WindowFunnelMode::FIXED) { if (event_data[match_row] == 1) { auto current_timestamp = timestamp_data[match_row]; - if (current_timestamp <= end_timestamp) { + if (_within_window(first_timestamp, current_timestamp, end_timestamp)) { matched_count++; continue; } @@ -200,7 +215,8 @@ struct WindowFunnelState { match_row = simd::find_one(event_data.data(), match_row, row_count); if (match_row < row_count) { auto current_timestamp = timestamp_data[match_row]; - bool is_matched = current_timestamp <= end_timestamp; + bool is_matched = + _within_window(first_timestamp, current_timestamp, end_timestamp); if (is_matched) { if constexpr (WINDOW_FUNNEL_MODE == WindowFunnelMode::INCREASE) { is_matched = current_timestamp > prev_timestamp; @@ -336,7 +352,11 @@ struct WindowFunnelState { for (auto i = 0; i < size; i++) { Int64 timestamp = 0; read_var_int(timestamp, in); - events_list.dt[i] = DateValueType(static_cast(timestamp)); + if constexpr (T == TYPE_TIMESTAMP_NS) { + events_list.dt[i] = DateValueType(timestamp); + } else { + events_list.dt[i] = DateValueType(static_cast(timestamp)); + } } events_list.event_columns_data.resize(event_count); for (int64_t i = 0; i < event_count; i++) { diff --git a/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.cpp b/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.cpp index e54ec1f92b7e74..1dc57c90a23672 100644 --- a/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.cpp +++ b/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.cpp @@ -41,6 +41,9 @@ AggregateFunctionPtr create_aggregate_function_window_funnel_v2(const std::strin if (argument_types[2]->get_primitive_type() == TYPE_DATETIMEV2) { return creator_without_type::create>( argument_types, result_is_nullable, attr); + } else if (argument_types[2]->get_primitive_type() == TYPE_TIMESTAMP_NS) { + return creator_without_type::create>( + argument_types, result_is_nullable, attr); } else if (argument_types[2]->get_primitive_type() == TYPE_TIMESTAMPTZ) { return creator_without_type::create>( argument_types, result_is_nullable, attr); diff --git a/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.h b/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.h index bef83a6dfe4889..af2fac10e73009 100644 --- a/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.h +++ b/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.h @@ -76,9 +76,11 @@ void merge_events_list(T& events_list, size_t prefix_size, bool prefix_sorted, b /// row has bit 7 = 0, and subsequent events from the same row have bit 7 = 1. /// The algorithm uses this to ensure each funnel step comes from a different row. /// -/// This approach adds ZERO storage overhead — each event remains 9 bytes (UInt64 + UInt8). +/// This approach adds ZERO storage overhead — each event remains 9 bytes (timestamp + UInt8). template struct WindowFunnelStateV2 { + using TimestampType = std::conditional_t; + /// (timestamp_int_val, 1-based event_index with continuation flag in bit 7) /// /// Bit layout of event_idx: @@ -89,7 +91,7 @@ struct WindowFunnelStateV2 { /// Sorted by timestamp only (via operator<). stable_sort preserves insertion order /// for equal timestamps, so same-row events remain consecutive after sorting. struct TimestampEvent { - UInt64 timestamp; + TimestampType timestamp; UInt8 event_idx; // includes continuation flag in bit 7 /// Sort by timestamp only. For same timestamp, stable_sort preserves insertion @@ -243,33 +245,46 @@ struct WindowFunnelStateV2 { } } - using DateValueType = DateV2Value; + using DateValueType = std::conditional_t>; - /// Reconstruct DateV2Value from packed UInt64. - static DateValueType _ts_from_int(UInt64 packed) { return DateValueType(packed); } + static DateValueType _ts_from_int(TimestampType timestamp) { return DateValueType(timestamp); } /// Check if `current_ts` is within `window` seconds of `base_ts`. - /// Both are packed UInt64 from DateV2Value::to_date_int_val(). - bool _within_window(UInt64 base_ts, UInt64 current_ts) const { - DateValueType end_ts = _ts_from_int(base_ts); - TimeInterval interval(SECOND, window, false); - end_ts.template date_add_interval(interval); - return current_ts <= end_ts.to_date_int_val(); + bool _within_window(TimestampType base_ts, TimestampType current_ts) const { + if constexpr (T == TYPE_TIMESTAMP_NS) { + const auto elapsed_nanos = + static_cast<__int128>(current_ts) - static_cast<__int128>(base_ts); + const auto window_nanos = + static_cast<__int128>(window) * TimeStampNsValue::NANOS_PER_SECOND; + return elapsed_nanos <= window_nanos; + } else { + DateValueType end_ts = _ts_from_int(base_ts); + TimeInterval interval(SECOND, window, false); + end_ts.template date_add_interval(interval); + return current_ts <= end_ts.to_date_int_val(); + } } /// Track (first_timestamp, last_timestamp, last_event_list_idx) for each event level. - /// Uses packed UInt64 values; 0 means unset for first_ts. /// last_list_idx tracks the position in events_list of the event that set this level, /// used to check continuation flag on subsequent events to detect same-row advancement. struct TimestampPair { - UInt64 first_ts = 0; - UInt64 last_ts = 0; + TimestampType first_ts = 0; + TimestampType last_ts = 0; size_t last_list_idx = 0; - bool has_value() const { return first_ts != 0; } + bool initialized = false; + bool has_value() const { + if constexpr (T == TYPE_TIMESTAMP_NS) { + return initialized; + } + return first_ts != 0; + } void reset() { first_ts = 0; last_ts = 0; last_list_idx = 0; + initialized = false; } }; @@ -316,13 +331,13 @@ struct WindowFunnelStateV2 { int event_idx = get_event_idx(evt.event_idx) - 1; if (event_idx == 0) { - events_timestamp[0] = {evt.timestamp, evt.timestamp, i}; + events_timestamp[0] = {evt.timestamp, evt.timestamp, i, true}; } else if (events_timestamp[event_idx - 1].has_value() && !_is_same_row(events_timestamp[event_idx - 1].last_list_idx, i)) { // Must be from a DIFFERENT row than the predecessor level if (_within_window(events_timestamp[event_idx - 1].first_ts, evt.timestamp)) { events_timestamp[event_idx] = {events_timestamp[event_idx - 1].first_ts, - evt.timestamp, i}; + evt.timestamp, i, true}; if (event_idx + 1 == event_count) { return event_count; } @@ -375,7 +390,7 @@ struct WindowFunnelStateV2 { // Try building a chain from this event-0 std::vector events_timestamp(event_count); events_timestamp[0] = {events_list[start].timestamp, events_list[start].timestamp, - start}; + start, true}; int curr_level = 0; for (size_t i = start + 1; i < list_size; ++i) { @@ -394,7 +409,7 @@ struct WindowFunnelStateV2 { matched = matched && events_timestamp[event_idx - 1].last_ts < evt.timestamp; if (matched) { events_timestamp[event_idx] = {events_timestamp[event_idx - 1].first_ts, - evt.timestamp, i}; + evt.timestamp, i, true}; curr_level = std::max(event_idx, curr_level); if (event_idx + 1 == event_count) { return event_count; @@ -436,7 +451,7 @@ struct WindowFunnelStateV2 { } // Build a chain from this event-0 - UInt64 first_ts = events_list[start].timestamp; + TimestampType first_ts = events_list[start].timestamp; int curr_level = 0; size_t last_advance_idx = start; @@ -518,7 +533,7 @@ struct WindowFunnelStateV2 { // Only start from c1 events (condition 0 in 0-based) if (get_event_idx(events_list[start_i].event_idx) != 1) continue; - UInt64 chain_start_ts = events_list[start_i].timestamp; + TimestampType chain_start_ts = events_list[start_i].timestamp; int curr_level = 0; // c1 is always the last event of its row, so start_i+1 is diff --git a/be/src/exprs/create_predicate_function.h b/be/src/exprs/create_predicate_function.h index b20c6613199d52..49b87750046032 100644 --- a/be/src/exprs/create_predicate_function.h +++ b/be/src/exprs/create_predicate_function.h @@ -92,6 +92,7 @@ class PredicateFunctionCreator { M(TYPE_DATETIME) \ M(TYPE_DATEV2) \ M(TYPE_DATETIMEV2) \ + M(TYPE_TIMESTAMP_NS) \ M(TYPE_TIMESTAMPTZ) \ M(TYPE_TIMEV2) \ M(TYPE_CHAR) \ diff --git a/be/src/exprs/function/array/function_array_aggregation.cpp b/be/src/exprs/function/array/function_array_aggregation.cpp index 671f39ea67114d..0140989891e450 100644 --- a/be/src/exprs/function/array/function_array_aggregation.cpp +++ b/be/src/exprs/function/array/function_array_aggregation.cpp @@ -189,6 +189,7 @@ struct ArrayAggregateImpl { execute_type(res, type, data, offsets) || execute_type(res, type, data, offsets) || execute_type(res, type, data, offsets) || + execute_type(res, type, data, offsets) || execute_type(res, type, data, offsets) || execute_type(res, type, data, offsets)) { block.replace_by_position(result, std::move(res)); @@ -261,8 +262,8 @@ struct ArrayAggregateImpl { if constexpr ((operation == AggregateOperation::SUM || operation == AggregateOperation::PRODUCT || operation == AggregateOperation::AVERAGE) && - (is_date_type(Element) || is_timestamptz_type(Element) || - is_decimalv3(Element))) { + (is_date_type(Element) || is_timestamp_ns_type(Element) || + is_timestamptz_type(Element) || is_decimalv3(Element))) { return false; } else { using ColVecType = typename PrimitiveTypeTraits::ColumnType; diff --git a/be/src/exprs/function/array/function_array_index.h b/be/src/exprs/function/array/function_array_index.h index 0984e803792859..58b535f8f27931 100644 --- a/be/src/exprs/function/array/function_array_index.h +++ b/be/src/exprs/function/array/function_array_index.h @@ -295,7 +295,13 @@ class FunctionArrayIndex : public IFunction { return_column = _execute_view(array_view, right_view); return true; }; - dispatch_switch_all(left_element_primitive_type, call); + // Keep nano dispatch local: the shared scalar dispatcher is also used by + // arithmetic-only templates that cannot be instantiated for datetime values. + if (left_element_primitive_type == TYPE_TIMESTAMP_NS) { + call(DispatchDataType()); + } else { + dispatch_switch_all(left_element_primitive_type, call); + } } if (return_column) { diff --git a/be/src/exprs/function/array/function_array_range.cpp b/be/src/exprs/function/array/function_array_range.cpp index 7f5dd187c7d66e..4ddf5bb4373f19 100644 --- a/be/src/exprs/function/array/function_array_range.cpp +++ b/be/src/exprs/function/array/function_array_range.cpp @@ -73,7 +73,7 @@ class FunctionArrayRange : public IFunction { } DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { - auto nested_type = make_nullable(Impl::get_data_type()); + auto nested_type = make_nullable(remove_nullable(arguments[0])); auto res = std::make_shared(nested_type); return make_nullable(res); } @@ -92,8 +92,9 @@ struct RangeImplUtil { static DataTypePtr get_data_type() { return std::make_shared(); } static constexpr const char* get_function_name() { - if constexpr (std::is_same_v> && - !std::is_same_v) { + if constexpr ((std::is_same_v> || + std::is_same_v)&&!std::is_same_v) { if constexpr (std::is_same_v>) { return "array_range_year_unit"; @@ -205,11 +206,8 @@ struct RangeImplUtil { dest_offsets.push_back(offset); } } else { - const auto& idx_0 = reinterpret_cast&>(idx); - const auto& end_row_cast = - reinterpret_cast&>(end_row); - bool is_null = !idx_0.is_valid_date(); - bool is_end_row_invalid = !end_row_cast.is_valid_date(); + bool is_null = !idx.is_valid_date(); + bool is_end_row_invalid = !end_row.is_valid_date(); if (args_null_map_row || step_row <= 0 || is_null || is_end_row_invalid) { args_null_map[row] = 1; dest_offsets.push_back(dest_offsets.back()); @@ -220,8 +218,7 @@ struct RangeImplUtil { std::integral_constant, TimeUnitOrVoid>; int move = 0; - while (doris::datetime_diff(idx, end_row) > 0) { + while (doris::datetime_diff(idx, end_row) > 0) { if (move > max_array_size_as_field) { return Status::InvalidArgument("Array size exceeds the limit {}", max_array_size_as_field); @@ -230,7 +227,7 @@ struct RangeImplUtil { dest_nested_null_map.push_back(0); offset++; move++; - idx = doris::date_time_add(idx, + idx = doris::date_time_add(idx, step_row); } dest_offsets.push_back(offset); @@ -305,6 +302,7 @@ void register_function_array_range(SimpleFunctionFactory& factory) { /// Two arguments, for Int32 and DateTimeV2 without Interval factory.register_function>>(); factory.register_function>>(); + factory.register_function>>(); /// Three arguments, for Int32 and DateTimeV2 with YEAR to SECOND Interval factory.register_function>>(); @@ -324,6 +322,22 @@ void register_function_array_range(SimpleFunctionFactory& factory) { RangeThreeImpl>>>(); factory.register_function>>>(); + factory.register_function>>>(); + factory.register_function>>>(); + factory.register_function>>>(); + factory.register_function>>>(); + factory.register_function>>>(); + factory.register_function>>>(); + factory.register_function>>>(); + factory.register_function>>>(); // alias factory.register_alias("array_range", "sequence"); diff --git a/be/src/exprs/function/cast/cast_to_basic_number_common.h b/be/src/exprs/function/cast/cast_to_basic_number_common.h index a9cc21b71ece62..eab96b42c27588 100644 --- a/be/src/exprs/function/cast/cast_to_basic_number_common.h +++ b/be/src/exprs/function/cast/cast_to_basic_number_common.h @@ -25,6 +25,7 @@ #include "core/data_type/data_type_decimal.h" #include "core/data_type/data_type_number.h" #include "core/data_type/data_type_string.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/data_type/define_primitive_type.h" #include "core/data_type/primitive_type.h" #include "core/types.h" @@ -393,6 +394,8 @@ Status static_cast_no_overflow(FunctionContext* context, Block& block, } else if constexpr (IsDatelikeV1Types) { CastToInt::from_datetime(reinterpret_cast(vec_from[i]), vec_to[i], params); + } else if constexpr (std::is_same_v) { + CastToInt::from_datetime(vec_from[i].to_datetime(), vec_to[i], params); } else if constexpr (IsDateTimeV2Type) { CastToInt::from_datetime( reinterpret_cast&>(vec_from[i]), @@ -418,6 +421,8 @@ Status static_cast_no_overflow(FunctionContext* context, Block& block, } else if constexpr (IsDatelikeV1Types) { CastToFloat::from_datetime(reinterpret_cast(vec_from[i]), vec_to[i], params); + } else if constexpr (std::is_same_v) { + CastToFloat::from_datetime(vec_from[i].to_datetime(), vec_to[i], params); } else if constexpr (IsDateTimeV2Type) { CastToFloat::from_datetime( reinterpret_cast&>(vec_from[i]), @@ -447,7 +452,8 @@ Status static_cast_no_overflow(FunctionContext* context, Block& block, template constexpr static bool type_allow_cast_to_basic_number = std::is_same_v || IsDataTypeNumber || IsDataTypeDecimal || - IsDatelikeV1Types || IsDatelikeV2Types || std::is_same_v; + IsDatelikeV1Types || IsDatelikeV2Types || std::is_same_v || + std::is_same_v; // common implementation for casting string to basic number types, // including integer, float and double diff --git a/be/src/exprs/function/cast/cast_to_date.h b/be/src/exprs/function/cast/cast_to_date.h index 009739b0b0bbbf..0ac9a2ed5d140f 100644 --- a/be/src/exprs/function/cast/cast_to_date.h +++ b/be/src/exprs/function/cast/cast_to_date.h @@ -19,6 +19,7 @@ #include +#include #include #include #include @@ -32,6 +33,7 @@ #include "core/data_type/data_type_number.h" #include "core/data_type/data_type_string.h" #include "core/data_type/data_type_time.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/data_type/primitive_type.h" #include "core/data_type_serde/data_type_serde.h" #include "core/types.h" @@ -129,6 +131,71 @@ class CastToImpl : public CastToBase { } }; +template + requires(std::is_same_v && IsDatelikeTypes) +class CastToImpl : public CastToBase { +public: + Status execute_impl(FunctionContext* /*context*/, Block& block, const ColumnNumbers& arguments, + uint32_t result, size_t input_rows_count, + const NullMap::value_type* null_map = nullptr) const override { + const auto& col_from = + assert_cast(*block.get_by_position(arguments[0]).column); + auto col_to = ToDataType::ColumnType::create(input_rows_count); + + for (size_t i = 0; i < input_rows_count; ++i) { + if (null_map && null_map[i]) { + continue; + } + + const auto& source = col_from.get_data()[i]; + const auto civil = source.to_datetime(); + if constexpr (IsDateType) { + DataTypeDateTimeV2::cast_to_date(civil, col_to->get_data()[i]); + } else if constexpr (IsDateV2Type) { + DataTypeDateTimeV2::cast_to_date_v2(civil, col_to->get_data()[i]); + } else if constexpr (IsDateTimeType) { + DataTypeDateTimeV2::cast_to_date_time(civil, col_to->get_data()[i]); + } else if constexpr (IsDateTimeV2Type) { + const auto to_scale = block.get_by_position(result).type->get_scale(); + const bool success = + transform_date_scale(to_scale, TimeStampNsValue::FRACTIONAL_DIGITS, + col_to->get_data()[i], source); + DORIS_CHECK(success); + } else { + static_assert(IsTimeV2Type); + const auto to_scale = block.get_by_position(result).type->get_scale(); + uint32_t hour = civil.hour(); + uint32_t minute = civil.minute(); + uint32_t second = civil.second(); + uint32_t nanoseconds = source.nanosecond(); + const auto divisor = static_cast(common::exp10_i64(9 - to_scale)); + const uint32_t remainder = nanoseconds % divisor; + nanoseconds = nanoseconds / divisor * divisor; + if (remainder >= divisor / 2) { + nanoseconds += divisor; + } + uint32_t microseconds = nanoseconds / TimeStampNsValue::NANOS_PER_MICROSECOND; + if (microseconds >= TimeValue::ONE_SECOND_MICROSECONDS) { + microseconds = 0; + if (++second == 60) { + second = 0; + if (++minute == 60) { + minute = 0; + ++hour; + } + } + } + col_to->get_data()[i] = + ((hour * 60 + minute) * 60 + second) * TimeValue::ONE_SECOND_MICROSECONDS + + microseconds; + } + } + + block.get_by_position(result).column = std::move(col_to); + return Status::OK(); + } +}; + template requires(IsDatelikeTypes && IsDatelikeTypes) class CastToImpl : public CastToBase { @@ -482,4 +549,5 @@ class CastToImpl& datetime, + uint32_t& nanoseconds) { + DCHECK_LE(to_scale, 6); + const auto divisor = static_cast(common::exp10_i64(9 - to_scale)); + const uint32_t remainder = nanoseconds % divisor; + nanoseconds = nanoseconds / divisor * divisor; + if (remainder >= divisor / 2) { + nanoseconds += divisor; + } + if (nanoseconds >= TimeStampNsValue::NANOS_PER_SECOND) { + nanoseconds = 0; + if (!datetime.template date_add_interval( + TimeInterval {TimeUnit::SECOND, 1, false})) { + return false; + } + } + datetime.set_microsecond(nanoseconds / TimeStampNsValue::NANOS_PER_MICROSECOND); + return true; +} + +inline bool transform_date_scale(UInt32 to_scale, UInt32 /*from_scale*/, + DateV2Value& to_value, + const TimeStampNsValue& from_value) { + auto datetime = from_value.to_datetime(); + uint32_t nanoseconds = from_value.nanosecond(); + if (!round_timestamp_ns_fraction(to_scale, datetime, nanoseconds)) { + return false; + } + to_value = datetime; + return true; +} + inline bool transform_date_scale(UInt32 to_scale, UInt32 from_scale, PrimitiveTypeTraits::CppType& to_value, const PrimitiveTypeTraits::CppType& from_value) { diff --git a/be/src/exprs/function/cast/cast_to_float.h b/be/src/exprs/function/cast/cast_to_float.h index 1fe36677386e6b..a3d8a121579cfc 100644 --- a/be/src/exprs/function/cast/cast_to_float.h +++ b/be/src/exprs/function/cast/cast_to_float.h @@ -80,6 +80,7 @@ class CastToImpl : public CastToBase { template requires(IsDataTypeFloat && (IsDatelikeV1Types || IsDatelikeV2Types || + std::is_same_v || std::is_same_v)) class CastToImpl : public CastToBase { public: diff --git a/be/src/exprs/function/cast/cast_to_int.h b/be/src/exprs/function/cast/cast_to_int.h index fdf2490c12192d..bf7672d3c1119d 100644 --- a/be/src/exprs/function/cast/cast_to_int.h +++ b/be/src/exprs/function/cast/cast_to_int.h @@ -212,8 +212,9 @@ constexpr static bool int_allow_cast_from_datetime = template requires(((IsDateType || IsDateV2Type)&&int_allow_cast_from_date) || - ((IsDateTimeType || - IsDateTimeV2Type)&&int_allow_cast_from_datetime)) + ((IsDateTimeType || IsDateTimeV2Type || + std::is_same_v)&&int_allow_cast_from_datetime)) class CastToImpl : public CastToBase { public: Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, diff --git a/be/src/exprs/function/cast/cast_to_timestamp_ns.h b/be/src/exprs/function/cast/cast_to_timestamp_ns.h new file mode 100644 index 00000000000000..8fb4e8cf6f28f6 --- /dev/null +++ b/be/src/exprs/function/cast/cast_to_timestamp_ns.h @@ -0,0 +1,360 @@ +// 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. + +#pragma once + +#include + +#include +#include +#include +#include +#include + +#include "common/status.h" +#include "core/binary_cast.hpp" +#include "core/column/column_nullable.h" +#include "core/data_type/data_type_date_or_datetime_v2.h" +#include "core/data_type/data_type_date_time.h" +#include "core/data_type/data_type_decimal.h" +#include "core/data_type/data_type_number.h" +#include "core/data_type/data_type_string.h" +#include "core/data_type/data_type_time.h" +#include "core/data_type/data_type_timestamp_ns.h" +#include "core/data_type/data_type_timestamptz.h" +#include "core/data_type_serde/data_type_serde.h" +#include "core/types.h" +#include "core/value/time_value.h" +#include "core/value/timestamptz_value.h" +#include "exprs/function/cast/cast_base.h" +#include "exprs/function/cast/cast_to_datetimev2_impl.hpp" +#include "runtime/runtime_state.h" +#include "util/string_parser.hpp" + +namespace doris { + +struct CastToTimestampNs { + // Floating-point input has no fixed decimal scale. Format it with the shortest round-trippable + // decimal representation, then reuse the decimal parser so digits 7-9 are not lost through a + // binary floating-point-to-microsecond conversion. + template + requires std::is_floating_point_v + static bool from_float(T float_value, TimeStampNsValue& result, CastParameters& params) { + if (params.is_strict) { + return from_float(float_value, result, params); + } + return from_float(float_value, result, params); + } + + template + requires std::is_floating_point_v + static bool from_float(T float_value, TimeStampNsValue& result, CastParameters& params) { + constexpr bool IsStrict = is_datelike_parse_strict(ParseMode); + DCHECK(IsStrict == params.is_strict); + SET_PARAMS_RET_FALSE_IFN( + float_value > 0 && !std::isnan(float_value) && !std::isinf(float_value), + "invalid float value for timestamp_ns: {}", float_value); + + std::array decimal_buffer {}; + const auto formatted = + fmt::format_to_n(decimal_buffer.data(), decimal_buffer.size(), "{}", float_value); + DCHECK_LE(formatted.size, decimal_buffer.size()); + StringParser::ParseResult parse_result = StringParser::PARSE_SUCCESS; + constexpr int decimal_scale = 18; + const auto decimal_value = StringParser::string_to_decimal( + decimal_buffer.data(), formatted.size, 38, decimal_scale, &parse_result); + SET_PARAMS_RET_FALSE_IFN(parse_result == StringParser::PARSE_SUCCESS, + "invalid float value for timestamp_ns: {}", float_value); + + constexpr auto scale_multiplier = decimal_scale_multiplier(decimal_scale); + return from_decimal(decimal_value / scale_multiplier, + decimal_value % scale_multiplier, decimal_scale, result, + params); + } + + template + static bool from_decimal(const T& int_part, const T& frac_part, int64_t decimal_scale, + TimeStampNsValue& result, CastParameters& params) { + if (params.is_strict) { + return from_decimal(int_part, frac_part, decimal_scale, + result, params); + } + return from_decimal(int_part, frac_part, decimal_scale, + result, params); + } + + template + static bool from_decimal(const T& int_part, const T& frac_part, int64_t decimal_scale, + TimeStampNsValue& result, CastParameters& params) { + constexpr bool IsStrict = is_datelike_parse_strict(ParseMode); + constexpr int64_t target_scale = TimeStampNsValue::FRACTIONAL_DIGITS; + DCHECK(IsStrict == params.is_strict); + SET_PARAMS_RET_FALSE_IFN(int_part <= std::numeric_limits::max() && int_part >= 1, + "invalid decimal value for timestamp_ns: {}.{}", int_part, + frac_part); + + DateV2Value datetime; + if (!CastToDatetimeV2::from_integer(int_part, datetime, params)) { + return false; + } + + T scaled_fraction = frac_part; + if (decimal_scale > target_scale) { + const auto divisor = decimal_scale_multiplier( + static_cast(decimal_scale - target_scale)); + const auto remainder = scaled_fraction % divisor; + scaled_fraction /= divisor; + if (remainder >= divisor / 2) { + ++scaled_fraction; + } + } else if (decimal_scale < target_scale) { + scaled_fraction *= decimal_scale_multiplier( + static_cast(target_scale - decimal_scale)); + } + + const auto fraction_limit = + decimal_scale_multiplier(static_cast(target_scale)); + if (scaled_fraction == fraction_limit) { + SET_PARAMS_RET_FALSE_IFN(datetime.template date_add_interval( + TimeInterval {TimeUnit::SECOND, 1, false}), + "timestamp_ns overflow when rounding up to next second"); + scaled_fraction = 0; + } + + const auto nanoseconds = static_cast(scaled_fraction); + datetime.set_microsecond(nanoseconds / TimeStampNsValue::NANOS_PER_MICROSECOND); + SET_PARAMS_RET_FALSE_IFN( + result.from_datetime(datetime, + nanoseconds % TimeStampNsValue::NANOS_PER_MICROSECOND), + "timestamp_ns value is outside the signed epoch-nanosecond range"); + return true; + } +}; + +template + requires IsStringType +class CastToImpl : public CastToBase { +public: + Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, + uint32_t result, size_t /*input_rows_count*/, + const NullMap::value_type* null_map = nullptr) const override { + const auto* col_from = assert_cast( + block.get_by_position(arguments[0]).column.get()); + + auto nested_to_type = remove_nullable(block.get_by_position(result).type); + auto serde = nested_to_type->get_serde(); + + DataTypeSerDe::FormatOptions options; + options.timezone = &context->state()->timezone_obj(); + + if constexpr (CastMode == CastModeType::StrictMode) { + MutableColumnPtr column_to = nested_to_type->create_column(); + RETURN_IF_ERROR( + serde->from_string_strict_mode_batch(*col_from, *column_to, options, null_map)); + block.get_by_position(result).column = std::move(column_to); + } else { + auto nullable_col_to = create_empty_nullable_column(nested_to_type); + RETURN_IF_ERROR(serde->from_string_batch(*col_from, *nullable_col_to, options)); + block.get_by_position(result).column = std::move(nullable_col_to); + } + + return Status::OK(); + } +}; + +template + requires CastUtil::IsPureDigitType +class CastToImpl : public CastToBase { +public: + Status execute_impl(FunctionContext* /*context*/, Block& block, const ColumnNumbers& arguments, + uint32_t result, size_t input_rows_count, + const NullMap::value_type* null_map = nullptr) const override { + const auto& col_from = assert_cast( + *block.get_by_position(arguments[0]).column); + auto col_to = ColumnTimeStampNs::create(input_rows_count); + auto col_nullmap = ColumnUInt8::create(input_rows_count, 0); + + for (size_t i = 0; i < input_rows_count; ++i) { + if (null_map && null_map[i]) { + continue; + } + + Status status = Status::OK(); + TimeStampNsValue value; + CastParameters params {.status = Status::OK(), + .is_strict = CastMode == CastModeType::StrictMode}; + bool parsed = false; + if constexpr (IsDataTypeDecimal) { + parsed = CastToTimestampNs::from_decimal(col_from.get_intergral_part(i), + col_from.get_fractional_part(i), + col_from.get_scale(), value, params); + } else if constexpr (IsDataTypeInt) { + DateV2Value datetime; + parsed = + CastToDatetimeV2::from_integer(col_from.get_element(i), datetime, params) && + value.from_datetime(datetime); + if (!parsed && params.status.ok()) { + status = Status::InvalidArgument( + "timestamp_ns value is outside the signed epoch-nanosecond range"); + } + } else { + static_assert(IsDataTypeFloat); + parsed = CastToTimestampNs::from_float(col_from.get_element(i), value, params); + } + if (!parsed && status.ok()) { + status = params.status.ok() + ? Status::InvalidArgument("Invalid numeric datetime value") + : params.status; + } + + if (!status.ok()) { + if constexpr (CastMode == CastModeType::StrictMode) { + status.prepend( + fmt::format("Cannot cast row {} from {} to TIMESTAMP_NS: ", i, + block.get_by_position(arguments[0]).type->get_name())); + return status; + } + col_nullmap->get_data()[i] = true; + } else { + col_to->get_data()[i] = value; + } + } + + if constexpr (CastMode == CastModeType::StrictMode) { + block.get_by_position(result).column = std::move(col_to); + } else { + block.get_by_position(result).column = + ColumnNullable::create(std::move(col_to), std::move(col_nullmap)); + } + return Status::OK(); + } +}; + +template + requires IsDatelikeTypes +class CastToImpl : public CastToBase { +public: + Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, + uint32_t result, size_t input_rows_count, + const NullMap::value_type* null_map = nullptr) const override { + const auto& col_from = assert_cast( + *block.get_by_position(arguments[0]).column); + auto col_to = ColumnTimeStampNs::create(input_rows_count); + auto col_nullmap = ColumnUInt8::create(input_rows_count, 0); + + for (size_t i = 0; i < input_rows_count; ++i) { + if (null_map && null_map[i]) { + continue; + } + + DateV2Value datetime; + if constexpr (IsDateType) { + const auto source = col_from.get_data()[i]; + datetime = binary_cast>( + source.to_datetime_v2()); + } else if constexpr (IsDateV2Type) { + DataTypeDateV2::cast_to_date_time_v2(col_from.get_data()[i], datetime); + } else if constexpr (IsDateTimeType) { + const auto source = col_from.get_data()[i]; + datetime = binary_cast>( + source.to_datetime_v2()); + } else if constexpr (IsDateTimeV2Type) { + datetime = col_from.get_data()[i]; + } else { + static_assert(IsTimeV2Type); + const auto scale = block.get_by_position(arguments[0]).type->get_scale(); + datetime.from_unixtime(context->state()->timestamp_ms() / 1000, + context->state()->nano_seconds(), + context->state()->timezone_obj(), scale); + datetime.reset_time_part(); + + const auto time_value = col_from.get_data()[i]; + const bool negative = TimeValue::sign(time_value) < 0; + datetime.template date_add_interval( + TimeInterval(HOUR, TimeValue::hour(time_value), negative)); + datetime.template date_add_interval( + TimeInterval(MINUTE, TimeValue::minute(time_value), negative)); + datetime.template date_add_interval( + TimeInterval(SECOND, TimeValue::second(time_value), negative)); + datetime.template date_add_interval( + TimeInterval(MICROSECOND, TimeValue::microsecond(time_value), negative)); + } + + if (!col_to->get_data()[i].from_datetime(datetime)) { + if constexpr (CastMode == CastModeType::StrictMode) { + return Status::InvalidArgument( + "TIMESTAMP_NS overflow when casting row {} from {} to TIMESTAMP_NS", i, + block.get_by_position(arguments[0]).type->get_name()); + } + col_nullmap->get_data()[i] = true; + } + } + + if constexpr (CastMode == CastModeType::StrictMode) { + block.get_by_position(result).column = std::move(col_to); + } else { + block.get_by_position(result).column = + ColumnNullable::create(std::move(col_to), std::move(col_nullmap)); + } + return Status::OK(); + } +}; + +template +class CastToImpl : public CastToBase { +public: + Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, + uint32_t result, size_t input_rows_count, + const NullMap::value_type* null_map = nullptr) const override { + const auto& col_from = + assert_cast(*block.get_by_position(arguments[0]).column) + .get_data(); + auto col_to = ColumnTimeStampNs::create(input_rows_count); + auto col_null = ColumnBool::create(input_rows_count, 0); + const auto& local_time_zone = context->state()->timezone_obj(); + const auto source_scale = block.get_by_position(arguments[0]).type->get_scale(); + + for (size_t i = 0; i < input_rows_count; ++i) { + if (null_map && null_map[i]) { + continue; + } + TimestampTzValue source {col_from[i]}; + DateV2Value datetime; + const bool converted = + source.to_datetime(datetime, local_time_zone, source_scale, source_scale) && + col_to->get_data()[i].from_datetime(datetime); + if (!converted) { + if constexpr (CastMode == CastModeType::StrictMode) { + return Status::InvalidArgument( + "can not cast timestamptz {} to TIMESTAMP_NS in timezone {}", + source.to_string(local_time_zone), context->state()->timezone()); + } + col_null->get_data()[i] = true; + } + } + + if constexpr (CastMode == CastModeType::StrictMode) { + block.get_by_position(result).column = std::move(col_to); + } else { + block.get_by_position(result).column = + ColumnNullable::create(std::move(col_to), std::move(col_null)); + } + return Status::OK(); + } +}; + +} // namespace doris diff --git a/be/src/exprs/function/cast/cast_to_timestamptz.h b/be/src/exprs/function/cast/cast_to_timestamptz.h index 5e7dcdb551e81f..8635329c7d5eab 100644 --- a/be/src/exprs/function/cast/cast_to_timestamptz.h +++ b/be/src/exprs/function/cast/cast_to_timestamptz.h @@ -19,6 +19,7 @@ #include "core/assert_cast.h" #include "core/data_type/data_type_date_or_datetime_v2.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/data_type/data_type_timestamptz.h" #include "core/data_type/primitive_type.h" #include "core/types.h" @@ -138,6 +139,53 @@ class CastToImpl +class CastToImpl : public CastToBase { +public: + Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, + uint32_t result, size_t input_rows_count, + const NullMap::value_type* null_map = nullptr) const override { + const auto& col_from = + assert_cast(*block.get_by_position(arguments[0]).column) + .get_data(); + auto col_to = ColumnTimeStampTz::create(input_rows_count); + auto col_null = ColumnBool::create(input_rows_count, 0); + const auto& local_time_zone = context->state()->timezone_obj(); + const auto target_scale = block.get_by_position(result).type->get_scale(); + + for (size_t i = 0; i < input_rows_count; ++i) { + if (null_map && null_map[i]) { + continue; + } + DateV2Value rounded_datetime; + TimestampTzValue target; + const bool converted = + transform_date_scale(target_scale, TimeStampNsValue::FRACTIONAL_DIGITS, + rounded_datetime, col_from[i]) && + target.from_datetime(rounded_datetime, local_time_zone, target_scale, + target_scale); + if (!converted) { + if constexpr (CastMode == CastModeType::StrictMode) { + return Status::InvalidArgument( + "can not cast TIMESTAMP_NS {} to timestamptz in timezone {}", + col_from[i].to_string(), context->state()->timezone()); + } + col_null->get_data()[i] = true; + continue; + } + col_to->get_data()[i] = target; + } + + if constexpr (CastMode == CastModeType::StrictMode) { + block.get_by_position(result).column = std::move(col_to); + } else { + block.get_by_position(result).column = + ColumnNullable::create(std::move(col_to), std::move(col_null)); + } + return Status::OK(); + } +}; + template <> class CastToImpl : public CastToBase { diff --git a/be/src/exprs/function/cast/cast_wrapper_decls.h b/be/src/exprs/function/cast/cast_wrapper_decls.h index 987c852880fd95..1bcd6bfde5d720 100644 --- a/be/src/exprs/function/cast/cast_wrapper_decls.h +++ b/be/src/exprs/function/cast/cast_wrapper_decls.h @@ -37,7 +37,10 @@ WrapperType create_decimal_wrapper(FunctionContext* context, const DataTypePtr& WrapperType create_datelike_wrapper(FunctionContext* context, const DataTypePtr& from_type, PrimitiveType to_type); -// Implemented in function_cast_date.cpp +// Implemented in function_cast_timestamp_ns.cpp +WrapperType create_timestamp_ns_wrapper(FunctionContext* context, const DataTypePtr& from_type); + +// Implemented in function_cast_timestamptz.cpp WrapperType create_timestamptz_wrapper(FunctionContext* context, const DataTypePtr& from_type); // Implemented in function_cast_ip.cpp diff --git a/be/src/exprs/function/cast/function_cast.cpp b/be/src/exprs/function/cast/function_cast.cpp index 5561a3a76de4a6..b4404e714f0d95 100644 --- a/be/src/exprs/function/cast/function_cast.cpp +++ b/be/src/exprs/function/cast/function_cast.cpp @@ -21,6 +21,7 @@ #include "core/data_type/data_type_decimal.h" #include "core/data_type/data_type_number.h" // IWYU pragma: keep #include "core/data_type/data_type_quantilestate.h" +#include "core/data_type/data_type_timestamp_ns.h" // IWYU pragma: keep #include "core/data_type/data_type_variant.h" #include "core/data_type/data_type_variant_v2.h" #include "core/data_type/primitive_type.h" @@ -314,6 +315,8 @@ WrapperType prepare_impl(FunctionContext* context, const DataTypePtr& origin_fro case PrimitiveType::TYPE_DATETIMEV2: case PrimitiveType::TYPE_TIMEV2: return create_datelike_wrapper(context, from_type, to_type->get_primitive_type()); + case PrimitiveType::TYPE_TIMESTAMP_NS: + return create_timestamp_ns_wrapper(context, from_type); case PrimitiveType::TYPE_TIMESTAMPTZ: return create_timestamptz_wrapper(context, from_type); case PrimitiveType::TYPE_IPV4: diff --git a/be/src/exprs/function/cast/function_cast_date.cpp b/be/src/exprs/function/cast/function_cast_date.cpp index 88013ab5e3a04b..104720ade61ec2 100644 --- a/be/src/exprs/function/cast/function_cast_date.cpp +++ b/be/src/exprs/function/cast/function_cast_date.cpp @@ -19,6 +19,7 @@ #include "core/data_type/data_type_date_or_datetime_v2.h" #include "core/data_type/data_type_date_time.h" #include "core/data_type/data_type_time.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "exprs/function/cast/cast_to_date.h" namespace doris::CastWrapper { @@ -30,7 +31,8 @@ WrapperType create_datelike_wrapper(FunctionContext* context, const DataTypePtr& auto make_datelike_wrapper = [&](const auto& types) -> bool { using Types = std::decay_t; using FromDataType = typename Types::LeftType; - if constexpr (CastUtil::IsPureDigitType || IsDatelikeTypes || + if constexpr (std::is_same_v || + CastUtil::IsPureDigitType || IsDatelikeTypes || IsStringType || std::is_same_v) { if (context->enable_strict_mode()) { diff --git a/be/src/exprs/function/cast/function_cast_timestamp_ns.cpp b/be/src/exprs/function/cast/function_cast_timestamp_ns.cpp new file mode 100644 index 00000000000000..9b86a3d3235da9 --- /dev/null +++ b/be/src/exprs/function/cast/function_cast_timestamp_ns.cpp @@ -0,0 +1,59 @@ +// 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 "exprs/function/cast/cast_to_timestamp_ns.h" + +namespace doris::CastWrapper { + +WrapperType create_timestamp_ns_wrapper(FunctionContext* context, const DataTypePtr& from_type) { + std::shared_ptr cast_to_timestamp_ns; + + auto make_timestamp_ns_wrapper = [&](const auto& types) -> bool { + using Types = std::decay_t; + using FromDataType = typename Types::LeftType; + if constexpr (IsStringType || CastUtil::IsPureDigitType || + IsDatelikeTypes || + std::is_same_v) { + if (context->enable_strict_mode()) { + cast_to_timestamp_ns = std::make_shared< + CastToImpl>(); + } else { + cast_to_timestamp_ns = + std::make_shared>(); + } + return true; + } + return false; + }; + + if (!call_on_index_and_data_type(from_type->get_primitive_type(), + make_timestamp_ns_wrapper)) { + return create_unsupport_wrapper( + fmt::format("CAST AS TIMESTAMP_NS not supported {}", from_type->get_name())); + } + + return [cast_to_timestamp_ns](FunctionContext* context, Block& block, + const ColumnNumbers& arguments, uint32_t result, + size_t input_rows_count, + const NullMap::value_type* null_map = nullptr) { + return cast_to_timestamp_ns->execute_impl(context, block, arguments, result, + input_rows_count, null_map); + }; +} + +} // namespace doris::CastWrapper diff --git a/be/src/exprs/function/cast/function_cast_timestamptz.cpp b/be/src/exprs/function/cast/function_cast_timestamptz.cpp index a26e1d5c5c2a5f..a2d30292370bfa 100644 --- a/be/src/exprs/function/cast/function_cast_timestamptz.cpp +++ b/be/src/exprs/function/cast/function_cast_timestamptz.cpp @@ -25,7 +25,8 @@ WrapperType create_timestamptz_wrapper(FunctionContext* context, const DataTypeP using Types = std::decay_t; using FromDataType = typename Types::LeftType; if constexpr (CastUtil::IsBaseCastFromType || - IsTimeStampTzType) { + IsTimeStampTzType || + std::is_same_v) { if (context->enable_strict_mode()) { cast_to_timestamptz = std::make_shared< CastToImpl>(); diff --git a/be/src/exprs/function/cast/variant_v2/cast_variant_to_scalar.cpp b/be/src/exprs/function/cast/variant_v2/cast_variant_to_scalar.cpp index 26aa100875985e..829a11649cd734 100644 --- a/be/src/exprs/function/cast/variant_v2/cast_variant_to_scalar.cpp +++ b/be/src/exprs/function/cast/variant_v2/cast_variant_to_scalar.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -36,6 +37,7 @@ #include "core/data_type/data_type_nullable.h" #include "core/data_type/data_type_number.h" #include "core/data_type/data_type_string.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/data_type/data_type_timestamptz.h" #include "core/value/timestamptz_value.h" #include "core/value/vdatetime_value.h" @@ -57,7 +59,8 @@ enum GroupIndex : size_t { DECIMAL_GROUP_BEGIN = DOUBLE_GROUP + 1, DATE_GROUP = DECIMAL_GROUP_BEGIN + DECIMAL_SCALE_COUNT, TIMESTAMP_NTZ_GROUP = DATE_GROUP + 1, - TIMESTAMP_TZ_GROUP = TIMESTAMP_NTZ_GROUP + 1, + TIMESTAMP_NANOS_GROUP = TIMESTAMP_NTZ_GROUP + 1, + TIMESTAMP_TZ_GROUP = TIMESTAMP_NANOS_GROUP + 1, STRING_GROUP = TIMESTAMP_TZ_GROUP + 1, GROUP_COUNT = STRING_GROUP + 1, }; @@ -203,6 +206,29 @@ void append_timestamp(ScalarGroups& groups, size_t row, int64_t micros, bool utc group.source_rows.push_back(row); } +void append_timestamp_nanos(FunctionContext* context, ScalarGroups& groups, size_t row, + int64_t nanos, bool utc_adjusted) { + if (utc_adjusted) { + DORIS_CHECK(context != nullptr); + DORIS_CHECK(context->state() != nullptr); + const auto seconds = TimeStampNsValue(nanos).epoch_seconds(); + const auto instant = cctz::time_point(cctz::seconds(seconds)); + const auto offset = context->state()->timezone_obj().lookup(instant).offset; + const auto local_nanos = static_cast<__int128>(nanos) + + static_cast<__int128>(offset) * TimeStampNsValue::NANOS_PER_SECOND; + if (local_nanos < std::numeric_limits::min() || + local_nanos > std::numeric_limits::max()) { + append_invalid(groups, row); + return; + } + nanos = static_cast(local_nanos); + } + auto& group = initialize_group(groups, TIMESTAMP_NANOS_GROUP, + [] { return std::make_shared(); }); + assert_cast(*group.values).insert_value(TimeStampNsValue(nanos)); + group.source_rows.push_back(row); +} + void append_string(ScalarGroups& groups, size_t row, StringRef value) { auto& group = initialize_group(groups, STRING_GROUP, [] { return std::make_shared(); }); @@ -210,7 +236,8 @@ void append_string(ScalarGroups& groups, size_t row, StringRef value) { group.source_rows.push_back(row); } -void classify_value(ScalarGroups& groups, size_t row, VariantRef value, bool forced_null) { +void classify_value(FunctionContext* context, ScalarGroups& groups, size_t row, VariantRef value, + PrimitiveType target_primitive, bool forced_null) { if (forced_null) { append_invalid(groups, row); return; @@ -267,9 +294,17 @@ void classify_value(ScalarGroups& groups, size_t row, VariantRef value, bool for append_timestamp(groups, row, value.get_timestamp_ntz_micros(), false); return; case VariantPrimitiveId::TIMESTAMP_NANOS: + if (target_primitive == TYPE_TIMESTAMP_NS || target_primitive == TYPE_STRING) { + append_timestamp_nanos(context, groups, row, value.get_timestamp_nanos(), true); + return; + } append_timestamp(groups, row, nanos_to_micros(value.get_timestamp_nanos()), true); return; case VariantPrimitiveId::TIMESTAMP_NTZ_NANOS: + if (target_primitive == TYPE_TIMESTAMP_NS || target_primitive == TYPE_STRING) { + append_timestamp_nanos(context, groups, row, value.get_timestamp_ntz_nanos(), false); + return; + } append_timestamp(groups, row, nanos_to_micros(value.get_timestamp_ntz_nanos()), false); return; case VariantPrimitiveId::STRING: @@ -404,6 +439,7 @@ bool is_supported_scalar_target(const DataTypePtr& type) { case TYPE_DATEV2: case TYPE_DATETIME: case TYPE_DATETIMEV2: + case TYPE_TIMESTAMP_NS: case TYPE_TIMESTAMPTZ: case TYPE_IPV4: case TYPE_IPV6: @@ -450,7 +486,8 @@ Status cast_variant_refs_to_scalar(FunctionContext* context, std::spanget_primitive_type(), + !forced_nulls.empty() && forced_nulls[row] != 0); } return assemble_groups(context, groups, target_type, values.size(), output); } @@ -464,7 +501,8 @@ Status cast_encoded_variant_to_scalar(FunctionContext* context, const ColumnVari } ScalarGroups groups; for (size_t row = 0; row < rows; ++row) { - classify_value(groups, row, source.get_value_ref(row), + classify_value(context, groups, row, source.get_value_ref(row), + target_type->get_primitive_type(), !forced_nulls.empty() && forced_nulls[row] != 0); } return assemble_groups(context, groups, target_type, rows, output); @@ -479,7 +517,10 @@ Status cast_variant_values_to_scalar(FunctionContext* context, const ColumnVaria ScalarGroups groups; visit_variant_v2_values( source, 0, rows, forced_nulls, [&](size_t row) { append_invalid(groups, row); }, - [&](size_t row, VariantRef value) { classify_value(groups, row, value, false); }); + [&](size_t row, VariantRef value) { + classify_value(context, groups, row, value, target_type->get_primitive_type(), + false); + }); return assemble_groups(context, groups, target_type, rows, output); } diff --git a/be/src/exprs/function/date_format_type.h b/be/src/exprs/function/date_format_type.h index 65566a91500cab..629d4e2df2d880 100644 --- a/be/src/exprs/function/date_format_type.h +++ b/be/src/exprs/function/date_format_type.h @@ -112,7 +112,8 @@ struct yyyy_MM_dd_HH_mm_ssImpl { struct yyyy_MM_dd_HH_mm_ss_SSSSSSImpl { constexpr static size_t row_size = 26; - size_t static date_to_str(const DateV2Value& date_value, char* buf) { + template + size_t static date_to_str(const DateType& date_value, char* buf) { int i = 0; put_year(date_value.year(), buf, i); buf[i++] = '-'; diff --git a/be/src/exprs/function/date_time_transforms.h b/be/src/exprs/function/date_time_transforms.h index 6bc2d6ed92f01b..9ed41087dae148 100644 --- a/be/src/exprs/function/date_time_transforms.h +++ b/be/src/exprs/function/date_time_transforms.h @@ -145,6 +145,11 @@ struct ToDateImpl { } else if constexpr (std::is_same_v) { t.cast_to_date(); return t; + } else if constexpr (std::is_same_v) { + DateV2Value result; + const auto civil_value = t.to_datetime(); + DataTypeDateTimeV2::cast_to_date_v2(civil_value, result); + return result; } else { return binary_cast>( (UInt32)(t.to_date_int_val() >> TIME_PART_LENGTH)); @@ -205,14 +210,20 @@ struct ToIso8601Impl { static constexpr PrimitiveType OpArgType = PType; using ArgType = typename PrimitiveTypeTraits::CppType; static constexpr auto name = "to_iso8601"; - static constexpr auto max_size = PType == TYPE_DATEV2 ? 10 : 26; + static constexpr auto max_size = + PType == TYPE_DATEV2 ? 10 : (PType == TYPE_TIMESTAMP_NS ? 29 : 26); static auto execute(const typename PrimitiveTypeTraits::CppType& dt, ColumnString::Chars& res_data, size_t& offset, const char* const* /*names_ptr*/, FunctionContext* /*context*/) { - auto length = dt.to_buffer((char*)res_data.data() + offset, - std::is_same_v ? -1 : 6); - if (PType == TYPE_DATETIMEV2 || PType == TYPE_TIMESTAMPTZ) { + int length = 0; + if constexpr (PType == TYPE_TIMESTAMP_NS) { + length = dt.to_buffer((char*)res_data.data() + offset); + } else { + constexpr int scale = PType == TYPE_DATEV2 ? -1 : 6; + length = dt.to_buffer((char*)res_data.data() + offset, scale); + } + if (PType == TYPE_DATETIMEV2 || PType == TYPE_TIMESTAMP_NS || PType == TYPE_TIMESTAMPTZ) { res_data[offset + 10] = 'T'; } @@ -302,10 +313,11 @@ struct MonthNameImpl { } }; -template +template struct DateTimeV2FormatImpl { - static constexpr PrimitiveType OpArgType = TYPE_DATETIMEV2; - using ArgType = typename PrimitiveTypeTraits::CppType; + static_assert(PType == TYPE_DATETIMEV2 || PType == TYPE_TIMESTAMP_NS); + static constexpr PrimitiveType OpArgType = PType; + using ArgType = typename PrimitiveTypeTraits::CppType; static constexpr auto name = FuncName; static constexpr auto max_size = FormatImpl::row_size; @@ -317,7 +329,7 @@ struct DateTimeV2FormatImpl { } static DataTypes get_variadic_argument_types() { - return {std::make_shared::DataType>()}; + return {std::make_shared::DataType>()}; } }; @@ -333,21 +345,34 @@ inline constexpr char kMinuteSecondName[] = "minute_second"; inline constexpr char kMinuteMicrosecondName[] = "minute_microsecond"; inline constexpr char kSecondMicrosecondName[] = "second_microsecond"; -using YearMonthImpl = DateTimeV2FormatImpl; -using DayHourImpl = DateTimeV2FormatImpl; -using DayMinuteImpl = DateTimeV2FormatImpl; -using DaySecondImpl = DateTimeV2FormatImpl; +template +using YearMonthImpl = DateTimeV2FormatImpl; +template +using DayHourImpl = DateTimeV2FormatImpl; +template +using DayMinuteImpl = DateTimeV2FormatImpl; +template +using DaySecondImpl = + DateTimeV2FormatImpl; +template using DayMicrosecondImpl = - DateTimeV2FormatImpl; -using HourMinuteImpl = DateTimeV2FormatImpl; -using HourSecondImpl = DateTimeV2FormatImpl; + DateTimeV2FormatImpl; +template +using HourMinuteImpl = DateTimeV2FormatImpl; +template +using HourSecondImpl = DateTimeV2FormatImpl; +template using HourMicrosecondImpl = - DateTimeV2FormatImpl; -using MinuteSecondImpl = DateTimeV2FormatImpl; + DateTimeV2FormatImpl; +template +using MinuteSecondImpl = + DateTimeV2FormatImpl; +template using MinuteMicrosecondImpl = - DateTimeV2FormatImpl; + DateTimeV2FormatImpl; +template using SecondMicrosecondImpl = - DateTimeV2FormatImpl; + DateTimeV2FormatImpl; template struct DateFormatImpl { diff --git a/be/src/exprs/function/dictionary.h b/be/src/exprs/function/dictionary.h index 7bfa9c669651e5..6b89c6c21a1674 100644 --- a/be/src/exprs/function/dictionary.h +++ b/be/src/exprs/function/dictionary.h @@ -33,6 +33,7 @@ #include "core/data_type/data_type_ipv6.h" #include "core/data_type/data_type_number.h" #include "core/data_type/data_type_string.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/types.h" #include "exprs/function/cast_type_to_either.h" @@ -114,9 +115,9 @@ class IDictionary { return cast_type_to_either(type, - std::forward(f)); + DataTypeDateTimeV2, DataTypeTimeStampNs, DataTypeDecimal32, + DataTypeDecimal64, DataTypeDecimal128, DataTypeDecimal256>( + type, std::forward(f)); } virtual size_t allocated_bytes() const; @@ -189,6 +190,7 @@ class IDictionary { ColumnWithType, ColumnWithType, ColumnWithType, ColumnWithType, + ColumnWithType, ColumnWithType, ColumnWithType, ColumnWithType, ColumnWithType>; diff --git a/be/src/exprs/function/function.h b/be/src/exprs/function/function.h index 8307a6a1c7c1b0..cead13f3825126 100644 --- a/be/src/exprs/function/function.h +++ b/be/src/exprs/function/function.h @@ -60,18 +60,17 @@ struct FunctionAttr { bool new_version_bitmap_op_count {false}; }; -#define RETURN_REAL_TYPE_FOR_DATEV2_FUNCTION(TYPE) \ - bool is_nullable = false; \ - bool is_datev2 = false; \ - for (auto it : arguments) { \ - is_nullable = is_nullable || it.type->is_nullable(); \ - is_datev2 = is_datev2 || it.type->get_primitive_type() == TYPE_DATEV2 || \ - it.type->get_primitive_type() == TYPE_DATETIMEV2; \ - } \ - return is_nullable || !is_datev2 \ - ? make_nullable( \ - std::make_shared::DataType>()) \ - : std::make_shared::DataType>(); +#define RETURN_REAL_TYPE_FOR_DATEV2_FUNCTION(TYPE) \ + bool is_nullable = false; \ + bool is_datev2 = false; \ + for (auto it : arguments) { \ + is_nullable = is_nullable || it.type->is_nullable(); \ + is_datev2 = is_datev2 || it.type->get_primitive_type() == TYPE_DATEV2 || \ + it.type->get_primitive_type() == TYPE_DATETIMEV2 || \ + it.type->get_primitive_type() == TYPE_TIMESTAMP_NS; \ + } \ + DataTypePtr real_type = std::make_shared::DataType>(); \ + return is_nullable || !is_datev2 ? make_nullable(real_type) : real_type; #define SET_NULLMAP_IF_FALSE(EXPR) \ if (!EXPR) [[unlikely]] { \ diff --git a/be/src/exprs/function/function_convert_tz.cpp b/be/src/exprs/function/function_convert_tz.cpp index aa2966cbc3fd44..c8ffb081154fb7 100644 --- a/be/src/exprs/function/function_convert_tz.cpp +++ b/be/src/exprs/function/function_convert_tz.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "common/status.h" @@ -40,6 +41,7 @@ #include "core/data_type/data_type_date_time.h" #include "core/data_type/data_type_nullable.h" #include "core/data_type/data_type_string.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/data_type/define_primitive_type.h" #include "core/data_type/primitive_type.h" #include "core/string_ref.h" @@ -63,23 +65,34 @@ struct ConvertTzState { cctz::time_zone to_tz; }; +template class FunctionConvertTZ : public IFunction { - constexpr static PrimitiveType PType = PrimitiveType::TYPE_DATETIMEV2; + constexpr static PrimitiveType PType = Type; using DateValueType = PrimitiveTypeTraits::CppType; using ColumnType = PrimitiveTypeTraits::ColumnType; public: static constexpr auto name = "convert_tz"; - static FunctionPtr create() { return std::make_shared(); } + static FunctionPtr create() { return std::make_shared>(); } String get_name() const override { return name; } size_t get_number_of_arguments() const override { return 3; } + DataTypes get_variadic_argument_types_impl() const override { + return {std::make_shared::DataType>(), + std::make_shared(), std::make_shared()}; + } + DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { - return have_nullable(arguments) ? make_nullable(std::make_shared()) - : std::make_shared(); + DataTypePtr result_type; + if constexpr (PType == TYPE_TIMESTAMP_NS) { + result_type = std::make_shared(); + } else { + result_type = create_datetimev2(arguments[0]->get_scale()); + } + return have_nullable(arguments) ? make_nullable(result_type) : result_type; } // default value of timezone is invalid, should skip to avoid wrong exception @@ -212,17 +225,41 @@ class FunctionConvertTZ : public IFunction { } } - static std::pair unix_timestamp_for_convert_tz( + static std::tuple unix_timestamp_for_convert_tz( const DateValueType& ts_value, const cctz::time_zone& from_tz) { - cctz::civil_second civil_time(ts_value.year(), ts_value.month(), ts_value.day(), - ts_value.hour(), ts_value.minute(), ts_value.second()); + const auto civil_value = [&]() { + if constexpr (PType == TYPE_TIMESTAMP_NS) { + return ts_value.to_datetime(); + } else { + return ts_value; + } + }(); + cctz::civil_second civil_time(civil_value.year(), civil_value.month(), civil_value.day(), + civil_value.hour(), civil_value.minute(), + civil_value.second()); const auto lookup = from_tz.lookup(civil_time); const bool skipped = lookup.kind == cctz::time_zone::civil_lookup::SKIPPED; const auto tp = skipped ? lookup.trans : lookup.pre; // Skipped civil times map to the transition instant. Do not keep the // input fractional part inside a local time interval that never existed. - return {tp.time_since_epoch().count(), skipped ? 0 : ts_value.microsecond()}; + return {tp.time_since_epoch().count(), skipped ? 0 : civil_value.microsecond(), skipped}; + } + + static bool convert_value(const DateValueType& source, const cctz::time_zone& from_tz, + const cctz::time_zone& to_tz, DateValueType* result) { + const auto [seconds, microseconds, skipped] = + unix_timestamp_for_convert_tz(source, from_tz); + const std::pair timestamp {seconds, microseconds}; + if constexpr (PType == TYPE_TIMESTAMP_NS) { + DateV2Value converted; + converted.from_unixtime(timestamp, to_tz); + const uint16_t remainder = skipped ? 0 : source.nanosecond_remainder(); + return result->from_datetime(converted, remainder); + } else { + result->from_unixtime(timestamp, to_tz); + return result->is_valid_date(); + } } static void execute_tz_const_with_state(ConvertTzState* convert_tz_state, @@ -252,14 +289,12 @@ class FunctionConvertTZ : public IFunction { DateValueType ts_value = date_column->get_element(i); DateValueType ts_value2; - ts_value2.from_unixtime(unix_timestamp_for_convert_tz(ts_value, from_tz), to_tz); - - if (!ts_value2.is_valid_date()) [[unlikely]] { + if (!convert_value(ts_value, from_tz, to_tz, &ts_value2)) [[unlikely]] { throw_out_of_bound_convert_tz(date_column->get_element(i), from_tz.name(), to_tz.name()); } - result_column->insert(Field::create_field(ts_value2)); + result_column->insert(Field::create_field(ts_value2)); } } @@ -303,19 +338,18 @@ class FunctionConvertTZ : public IFunction { to_tz_name); } - ts_value2.from_unixtime(unix_timestamp_for_convert_tz(ts_value, from_tz), to_tz); - - if (!ts_value2.is_valid_date()) [[unlikely]] { + if (!convert_value(ts_value, from_tz, to_tz, &ts_value2)) [[unlikely]] { throw_out_of_bound_convert_tz(date_column->get_element(index_now), from_tz.name(), to_tz.name()); } - result_column->insert(Field::create_field(ts_value2)); + result_column->insert(Field::create_field(ts_value2)); } }; void register_function_convert_tz(SimpleFunctionFactory& factory) { - factory.register_function(); + factory.register_function>(); + factory.register_function>(); } } // namespace doris diff --git a/be/src/exprs/function/function_date_or_datetime_computation.cpp b/be/src/exprs/function/function_date_or_datetime_computation.cpp index 8973cab77e36a1..e5216241e3ce7e 100644 --- a/be/src/exprs/function/function_date_or_datetime_computation.cpp +++ b/be/src/exprs/function/function_date_or_datetime_computation.cpp @@ -88,6 +88,32 @@ using FunctionDatetimeAddWeeks = FunctionDateOrDateTimeComputation>; using FunctionDatetimeAddYears = FunctionDateOrDateTimeComputation>; +#define TIMESTAMP_NS_COMPUTATION_ALIAS(NAME, IMPL) \ + using FunctionTimeStampNs##NAME = FunctionDateOrDateTimeComputation> + +TIMESTAMP_NS_COMPUTATION_ALIAS(AddMicroseconds, AddMicrosecondsImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(AddMilliseconds, AddMillisecondsImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(AddSeconds, AddSecondsImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(AddMinutes, AddMinutesImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(AddHours, AddHoursImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(AddDays, AddDaysImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(AddWeeks, AddWeeksImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(AddMonths, AddMonthsImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(AddYears, AddYearsImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(AddQuarters, AddQuartersImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(SubMicroseconds, SubtractMicrosecondsImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(SubMilliseconds, SubtractMillisecondsImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(SubSeconds, SubtractSecondsImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(SubMinutes, SubtractMinutesImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(SubHours, SubtractHoursImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(SubDays, SubtractDaysImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(SubWeeks, SubtractWeeksImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(SubMonths, SubtractMonthsImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(SubQuarters, SubtractQuartersImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(SubYears, SubtractYearsImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(ToYearWeekTwoArgs, ToYearWeekTwoArgsImpl); +TIMESTAMP_NS_COMPUTATION_ALIAS(ToWeekTwoArgs, ToWeekTwoArgsImpl); + using FunctionTimestamptzAddMicroseconds = FunctionDateOrDateTimeComputation>; using FunctionTimestamptzAddMilliseconds = @@ -105,14 +131,18 @@ using FunctionTimestamptzAddMonths = FunctionDateOrDateTimeComputation>; using FunctionTimestamptzAddYears = FunctionDateOrDateTimeComputation>; -#define FUNCTION_TIME_UNION_CAL(TYPE) \ - using FunctionDatetimeAdd##TYPE = \ - FunctionDateOrDateTimeComputation>; \ - using FunctionDatetimeSub##TYPE = \ - FunctionDateOrDateTimeComputation>; \ - using FunctionTimestamptzAdd##TYPE = \ - FunctionDateOrDateTimeComputation>; \ - using FunctionTimestamptzSub##TYPE = \ +#define FUNCTION_TIME_UNION_CAL(TYPE) \ + using FunctionDatetimeAdd##TYPE = \ + FunctionDateOrDateTimeComputation>; \ + using FunctionDatetimeSub##TYPE = \ + FunctionDateOrDateTimeComputation>; \ + using FunctionTimeStampNsAdd##TYPE = \ + FunctionDateOrDateTimeComputation>; \ + using FunctionTimeStampNsSub##TYPE = \ + FunctionDateOrDateTimeComputation>; \ + using FunctionTimestamptzAdd##TYPE = \ + FunctionDateOrDateTimeComputation>; \ + using FunctionTimestamptzSub##TYPE = \ FunctionDateOrDateTimeComputation>; FUNCTION_TIME_UNION_CAL(SecondMicrosecond); @@ -174,19 +204,24 @@ using FunctionTimestamptzSubYears = FunctionDateOrDateTimeComputation>; using FunctionAddTimeDatetime = FunctionNeedsToHandleNull; +using FunctionAddTimeTimeStampNs = + FunctionNeedsToHandleNull; using FunctionAddTimeTime = FunctionNeedsToHandleNull; using FunctionAddTimeTimestampTz = FunctionNeedsToHandleNull; using FunctionSubTimeDatetime = FunctionNeedsToHandleNull; +using FunctionSubTimeTimeStampNs = + FunctionNeedsToHandleNull; using FunctionSubTimeTime = FunctionNeedsToHandleNull; using FunctionSubTimeTimestampTz = FunctionNeedsToHandleNull; #define FUNCTION_TIME_DIFF(NAME, IMPL, TYPE) using NAME##_##TYPE = FunctionTimeDiff>; -#define ALL_FUNCTION_TIME_DIFF(NAME, IMPL) \ - FUNCTION_TIME_DIFF(NAME, IMPL, TYPE_DATETIMEV2) \ - FUNCTION_TIME_DIFF(NAME, IMPL, TYPE_DATEV2) \ +#define ALL_FUNCTION_TIME_DIFF(NAME, IMPL) \ + FUNCTION_TIME_DIFF(NAME, IMPL, TYPE_DATETIMEV2) \ + FUNCTION_TIME_DIFF(NAME, IMPL, TYPE_TIMESTAMP_NS) \ + FUNCTION_TIME_DIFF(NAME, IMPL, TYPE_DATEV2) \ FUNCTION_TIME_DIFF(NAME, IMPL, TYPE_TIMESTAMPTZ) // these diff functions accept all v2 types. but for v1 only datetime. ALL_FUNCTION_TIME_DIFF(FunctionDatetimeDateDiff, DateDiffImpl) @@ -257,6 +292,16 @@ void register_function_date_time_computation(SimpleFunctionFactory& factory) { factory.register_function(); factory.register_function(); factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); factory.register_function(); factory.register_function(); factory.register_function(); @@ -271,6 +316,8 @@ void register_function_date_time_computation(SimpleFunctionFactory& factory) { #define REGISTER_TIME_UNION_CAL(TYPE) \ factory.register_function(); \ factory.register_function(); \ + factory.register_function(); \ + factory.register_function(); \ factory.register_function(); \ factory.register_function(); @@ -302,6 +349,16 @@ void register_function_date_time_computation(SimpleFunctionFactory& factory) { factory.register_function(); factory.register_function(); factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); factory.register_function(); factory.register_function(); @@ -315,17 +372,20 @@ void register_function_date_time_computation(SimpleFunctionFactory& factory) { factory.register_function(); factory.register_function(); + factory.register_function(); factory.register_function(); factory.register_function(); factory.register_function(); + factory.register_function(); factory.register_function(); factory.register_function(); #define REGISTER_DATEV2_FUNCTIONS_DIFF(NAME, TYPE) factory.register_function(); -#define REGISTER_ALL_DATEV2_FUNCTIONS_DIFF(NAME) \ - REGISTER_DATEV2_FUNCTIONS_DIFF(NAME, TYPE_DATETIMEV2) \ - REGISTER_DATEV2_FUNCTIONS_DIFF(NAME, TYPE_DATEV2) \ +#define REGISTER_ALL_DATEV2_FUNCTIONS_DIFF(NAME) \ + REGISTER_DATEV2_FUNCTIONS_DIFF(NAME, TYPE_DATETIMEV2) \ + REGISTER_DATEV2_FUNCTIONS_DIFF(NAME, TYPE_TIMESTAMP_NS) \ + REGISTER_DATEV2_FUNCTIONS_DIFF(NAME, TYPE_DATEV2) \ REGISTER_DATEV2_FUNCTIONS_DIFF(NAME, TYPE_TIMESTAMPTZ) REGISTER_ALL_DATEV2_FUNCTIONS_DIFF(FunctionDatetimeDateDiff) @@ -345,6 +405,8 @@ void register_function_date_time_computation(SimpleFunctionFactory& factory) { factory.register_function(); factory.register_function(); factory.register_function(); + factory.register_function(); + factory.register_function(); } -} // namespace doris \ No newline at end of file +} // namespace doris diff --git a/be/src/exprs/function/function_date_or_datetime_computation.h b/be/src/exprs/function/function_date_or_datetime_computation.h index db1bd7441fc826..5b2f002d15b3ad 100644 --- a/be/src/exprs/function/function_date_or_datetime_computation.h +++ b/be/src/exprs/function/function_date_or_datetime_computation.h @@ -573,8 +573,9 @@ struct TimeDiffImpl { using ValueType = typename PrimitiveTypeTraits::CppType; using ArgType = typename PrimitiveTypeTraits::DataType::FieldType; //TODO: remove V1 since FE already removed it. - static constexpr bool UsingTimev2 = - is_date_v2_or_datetime_v2(DateType) || DateType == TYPE_TIMESTAMPTZ; + static constexpr bool UsingTimev2 = is_date_v2_or_datetime_v2(DateType) || + DateType == TYPE_TIMESTAMP_NS || + DateType == TYPE_TIMESTAMPTZ; static constexpr PrimitiveType ReturnType = TYPE_TIMEV2; static constexpr auto name = "timediff"; @@ -596,10 +597,11 @@ struct TimeDiffImpl { } static DataTypePtr get_return_type_impl(const ColumnsWithTypeAndName& arguments) { + const auto scale = std::min(arguments[0].type->get_scale(), DataTypeTimeV2::MAX_SCALE); if (arguments[0].type->is_nullable() || arguments[1].type->is_nullable()) { - return make_nullable(std::make_shared(arguments[0].type->get_scale())); + return make_nullable(std::make_shared(scale)); } - return std::make_shared(arguments[0].type->get_scale()); + return std::make_shared(scale); } }; @@ -1613,19 +1615,32 @@ class FunctionTime : public IFunction { size_t get_number_of_arguments() const override { return 1; } DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { - return std::make_shared(arguments[0]->get_scale()); + return std::make_shared( + std::min(arguments[0]->get_scale(), DataTypeTimeV2::MAX_SCALE)); } Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, uint32_t result, size_t input_rows_count) const override { DCHECK_EQ(arguments.size(), 1); - ColumnPtr col = block.get_by_position(arguments[0]).column; - const auto& arg = assert_cast(*col.get()); + const auto& argument = block.get_by_position(arguments[0]); + if (argument.type->get_primitive_type() == TYPE_TIMESTAMP_NS) { + return execute_typed(block, arguments[0], result, input_rows_count); + } + DORIS_CHECK_EQ(argument.type->get_primitive_type(), TYPE_DATETIMEV2); + return execute_typed(block, arguments[0], result, input_rows_count); + } + +private: + template + Status execute_typed(Block& block, uint32_t argument, uint32_t result, + size_t input_rows_count) const { + const auto& arg = assert_cast::ColumnType&>( + *block.get_by_position(argument).column); ColumnTimeV2::MutablePtr res = ColumnTimeV2::create(input_rows_count); auto& res_data = res->get_data(); - for (int i = 0; i < arg.size(); i++) { + for (size_t i = 0; i < arg.size(); ++i) { const auto& v = arg.get_element(i); - // the arg is datetimev2 type, it's store as uint64, so we need to get arg's hour minute second part + // TIMEV2 has microsecond precision, so TIMESTAMP_NS intentionally drops digits 7-9. res_data[i] = TimeValue::make_time(v.hour(), v.minute(), v.second(), v.microsecond()); } block.replace_by_position(result, std::move(res)); @@ -1871,7 +1886,16 @@ class AddTimeImplBase { const auto& arg1 = left_data[index_check_const(i, cols_info[0].is_const)]; const auto& arg2 = right_data[index_check_const(i, cols_info[1].is_const)]; - if constexpr (PType == TYPE_DATETIMEV2 || PType == TYPE_TIMESTAMPTZ) { + if constexpr (PType == TYPE_TIMESTAMP_NS) { + auto result = arg1; + auto tv2 = static_cast(arg2); + TimeInterval interval(TimeUnit::MICROSECOND, tv2, IsNegative); + if (!result.template date_add_interval(interval)) + [[unlikely]] { + throw_invalid_strings(name, arg1.to_string(), std::to_string(arg2)); + } + res_col->insert_value(result); + } else if constexpr (PType == TYPE_DATETIMEV2 || PType == TYPE_TIMESTAMPTZ) { DateV2Value dtv1(arg1.to_date_int_val()); auto tv2 = static_cast(arg2); TimeInterval interval(TimeUnit::MICROSECOND, tv2, IsNegative); @@ -1893,9 +1917,11 @@ class AddTimeImplBase { }; using AddTimeDatetimeImpl = AddTimeImplBase; +using AddTimeTimeStampNsImpl = AddTimeImplBase; using AddTimeTimeImpl = AddTimeImplBase; using AddTimeTimestamptzImpl = AddTimeImplBase; using SubTimeDatetimeImpl = AddTimeImplBase; +using SubTimeTimeStampNsImpl = AddTimeImplBase; using SubTimeTimeImpl = AddTimeImplBase; using SubTimeTimestamptzImpl = AddTimeImplBase; #include "common/compile_check_avoid_end.h" diff --git a/be/src/exprs/function/function_date_or_datetime_to_something.h b/be/src/exprs/function/function_date_or_datetime_to_something.h index 6f0ee6fca269d9..17ed66e33630e7 100644 --- a/be/src/exprs/function/function_date_or_datetime_to_something.h +++ b/be/src/exprs/function/function_date_or_datetime_to_something.h @@ -49,7 +49,8 @@ struct Transformer { #endif auto res = Transform::execute(vec_from[i]); - if constexpr (is_date_type(ToPType) || ToPType == TYPE_TIMESTAMPTZ) { + if constexpr (is_date_type(ToPType) || ToPType == TYPE_TIMESTAMP_NS || + ToPType == TYPE_TIMESTAMPTZ) { vec_to[i] = res; } else { using RESULT_TYPE = std::decay_t; @@ -109,7 +110,8 @@ class FunctionDateOrDateTimeToSomething : public IFunction { DataTypePtr get_return_type_impl(const ColumnsWithTypeAndName& arguments) const override { if (arguments.size() == 1) { if (!is_date_or_datetime(arguments[0].type->get_primitive_type()) && - !is_date_v2_or_datetime_v2(arguments[0].type->get_primitive_type())) { + !is_date_v2_or_datetime_v2(arguments[0].type->get_primitive_type()) && + arguments[0].type->get_primitive_type() != TYPE_TIMESTAMP_NS) { throw doris::Exception(ErrorCode::INVALID_ARGUMENT, "Illegal type {} of argument of function {}. Should be a " "date or a date with time", @@ -117,7 +119,8 @@ class FunctionDateOrDateTimeToSomething : public IFunction { } } else if (arguments.size() == 2) { if (!is_date_or_datetime(arguments[0].type->get_primitive_type()) && - !is_date_v2_or_datetime_v2(arguments[0].type->get_primitive_type())) { + !is_date_v2_or_datetime_v2(arguments[0].type->get_primitive_type()) && + arguments[0].type->get_primitive_type() != TYPE_TIMESTAMP_NS) { throw doris::Exception(ErrorCode::INVALID_ARGUMENT, "Illegal type {} of argument of function {}. Should be a " "date or a date with time", diff --git a/be/src/exprs/function/function_date_or_datetime_to_string.cpp b/be/src/exprs/function/function_date_or_datetime_to_string.cpp index c7b240df961901..9515e90c46f7cb 100644 --- a/be/src/exprs/function/function_date_or_datetime_to_string.cpp +++ b/be/src/exprs/function/function_date_or_datetime_to_string.cpp @@ -212,20 +212,30 @@ using FunctionMonthNameV2 = FunctionDateOrDateTimeToString>; using FunctionDateTimeV2MonthName = FunctionDateOrDateTimeToString>; -using FunctionYearMonth = FunctionDateOrDateTimeToString; -using FunctionDayHour = FunctionDateOrDateTimeToString; -using FunctionDayMinute = FunctionDateOrDateTimeToString; -using FunctionDaySecond = FunctionDateOrDateTimeToString; -using FunctionDayMicrosecond = FunctionDateOrDateTimeToString; -using FunctionHourMinute = FunctionDateOrDateTimeToString; -using FunctionHourSecond = FunctionDateOrDateTimeToString; -using FunctionHourMicrosecond = FunctionDateOrDateTimeToString; -using FunctionMinuteSecond = FunctionDateOrDateTimeToString; -using FunctionMinuteMicrosecond = FunctionDateOrDateTimeToString; -using FunctionSecondMicrosecond = FunctionDateOrDateTimeToString; +using FunctionTimestampNsDayName = FunctionDateOrDateTimeToString>; +using FunctionTimestampNsMonthName = + FunctionDateOrDateTimeToString>; +#define DEFINE_DATETIME_FORMAT_FUNCTION(NAME) \ + using Function##NAME = FunctionDateOrDateTimeToString>; \ + using FunctionTimestampNs##NAME = FunctionDateOrDateTimeToString> + +DEFINE_DATETIME_FORMAT_FUNCTION(YearMonth); +DEFINE_DATETIME_FORMAT_FUNCTION(DayHour); +DEFINE_DATETIME_FORMAT_FUNCTION(DayMinute); +DEFINE_DATETIME_FORMAT_FUNCTION(DaySecond); +DEFINE_DATETIME_FORMAT_FUNCTION(DayMicrosecond); +DEFINE_DATETIME_FORMAT_FUNCTION(HourMinute); +DEFINE_DATETIME_FORMAT_FUNCTION(HourSecond); +DEFINE_DATETIME_FORMAT_FUNCTION(HourMicrosecond); +DEFINE_DATETIME_FORMAT_FUNCTION(MinuteSecond); +DEFINE_DATETIME_FORMAT_FUNCTION(MinuteMicrosecond); +DEFINE_DATETIME_FORMAT_FUNCTION(SecondMicrosecond); + +#undef DEFINE_DATETIME_FORMAT_FUNCTION using FunctionDateIso8601 = FunctionDateOrDateTimeToString>; using FunctionDateTimeIso8601 = FunctionDateOrDateTimeToString>; +using FunctionTimeStampNsIso8601 = FunctionDateOrDateTimeToString>; using FunctionTimestampTzIso8601 = FunctionDateOrDateTimeToString>; void register_function_date_time_to_string(SimpleFunctionFactory& factory) { @@ -233,6 +243,8 @@ void register_function_date_time_to_string(SimpleFunctionFactory& factory) { factory.register_function(); factory.register_function(); factory.register_function(); + factory.register_function(); + factory.register_function(); factory.register_function(); factory.register_function(); factory.register_function(); @@ -244,8 +256,20 @@ void register_function_date_time_to_string(SimpleFunctionFactory& factory) { factory.register_function(); factory.register_function(); factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); factory.register_function(); factory.register_function(); + factory.register_function(); factory.register_function(); } diff --git a/be/src/exprs/function/function_datetime_floor_ceil.cpp b/be/src/exprs/function/function_datetime_floor_ceil.cpp index 6369dd9592cda3..5bc301320e560a 100644 --- a/be/src/exprs/function/function_datetime_floor_ceil.cpp +++ b/be/src/exprs/function/function_datetime_floor_ceil.cpp @@ -137,8 +137,8 @@ class FunctionDateTimeFloorCeil : public FunctionDateTimeFloorCeilBase { String get_name() const override { return name; } DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { - return have_nullable(arguments) ? make_nullable(std::make_shared()) - : std::make_shared(); + auto return_type = remove_nullable(arguments[0]); + return have_nullable(arguments) ? make_nullable(return_type) : return_type; } DataTypes get_variadic_argument_types_impl() const override { @@ -358,9 +358,11 @@ struct DateTimeFloorCeilCore { static void vector_const_const(const PaddedPODArray& dates, const Int32 period, DateValueType origin_date, PaddedPODArray& res, const NullMap& result_null_map, FunctionContext* context) { - if (auto cast_date = origin_date; cast_date == DateValueType::FIRST_DAY) { - vector_const_period(dates, period, res, result_null_map, context); - return; + if constexpr (!std::is_same_v) { + if (origin_date == DateValueType::FIRST_DAY) { + vector_const_period(dates, period, res, result_null_map, context); + return; + } } // expand codes for const input periods @@ -507,24 +509,37 @@ struct DateTimeFloorCeilCore { template static bool time_round_reinterpret_two_args(DateValueType date, Int32 period, DateValueType& res, FunctionContext* context) { - auto ts_arg = date; - auto& ts_res = res; - - if constexpr (const_period == 0) { - if (can_use_optimize(period)) { - floor_opt(ts_arg, ts_res, period); - return true; - } else { - ts_res = DateValueType::FIRST_DAY; - return time_round_two_args(ts_arg, period, ts_res, context); + if constexpr (std::is_same_v) { + auto legacy_date = date.to_datetime(); + if (date.nanosecond_remainder() != 0 && legacy_date.microsecond() == 0) { + legacy_date.template unchecked_set_time_unit(1); + } + auto legacy_result = DateV2Value::FIRST_DAY; + if (!DateTimeFloorCeilCore::template time_round_two_args< + const_period>(legacy_date, period, legacy_result, context)) { + return false; } + return res.from_datetime(legacy_result); } else { - if (can_use_optimize(const_period)) { - floor_opt(ts_arg, ts_res, const_period); - return true; + auto ts_arg = date; + auto& ts_res = res; + + if constexpr (const_period == 0) { + if (can_use_optimize(period)) { + floor_opt(ts_arg, ts_res, period); + return true; + } else { + ts_res = DateValueType::FIRST_DAY; + return time_round_two_args(ts_arg, period, ts_res, context); + } } else { - ts_res = DateValueType::FIRST_DAY; - return time_round_two_args(ts_arg, const_period, ts_res, context); + if (can_use_optimize(const_period)) { + floor_opt(ts_arg, ts_res, const_period); + return true; + } else { + ts_res = DateValueType::FIRST_DAY; + return time_round_two_args(ts_arg, const_period, ts_res, context); + } } } } @@ -739,6 +754,76 @@ struct DateTimeFloorCeilCore { trivial_part_ts_arg = calc_arg.microsecond(); trivial_part_ts_res = calc_origin.microsecond(); } + } else if constexpr (std::is_same_v) { + const auto nanos_since_midnight = [](const TimeStampNsValue& value) { + return value.time_part_to_seconds() * TimeStampNsValue::NANOS_PER_SECOND + + value.nanosecond(); + }; + const auto nanos_since_date = [&](const TimeStampNsValue& value, uint8_t month, + uint8_t day) { + return (value.daynr() - calc_daynr(value.year(), month, day)) * HOUR_PER_DAY * + SECOND_PER_HOUR * TimeStampNsValue::NANOS_PER_SECOND + + nanos_since_midnight(value); + }; + + if constexpr (Flag::Unit == YEAR) { + diff = ts_arg.year() - ts_origin.year(); + trivial_part_ts_arg = nanos_since_date(ts_arg, 1, 1); + trivial_part_ts_res = nanos_since_date(ts_origin, 1, 1); + } + if constexpr (Flag::Unit == QUARTER) { + diff = (ts_arg.year() - ts_origin.year()) * 4 + + (ts_arg.month() - ts_origin.month()) / 3; + const uint8_t arg_quarter_month = (ts_arg.month() - 1) / 3 * 3 + 1; + const uint8_t origin_quarter_month = (ts_origin.month() - 1) / 3 * 3 + 1; + trivial_part_ts_arg = nanos_since_date(ts_arg, arg_quarter_month, 1); + trivial_part_ts_res = nanos_since_date(ts_origin, origin_quarter_month, 1); + } + if constexpr (Flag::Unit == MONTH) { + diff = (ts_arg.year() - ts_origin.year()) * 12 + + (ts_arg.month() - ts_origin.month()); + trivial_part_ts_arg = nanos_since_date(ts_arg, ts_arg.month(), 1); + trivial_part_ts_res = nanos_since_date(ts_origin, ts_origin.month(), 1); + } + if constexpr (Flag::Unit == WEEK) { + diff = ts_arg.daynr() / 7 - ts_origin.daynr() / 7; + trivial_part_ts_arg = ts_arg.daynr() % 7 * HOUR_PER_DAY * SECOND_PER_HOUR * + TimeStampNsValue::NANOS_PER_SECOND + + nanos_since_midnight(ts_arg); + trivial_part_ts_res = ts_origin.daynr() % 7 * HOUR_PER_DAY * SECOND_PER_HOUR * + TimeStampNsValue::NANOS_PER_SECOND + + nanos_since_midnight(ts_origin); + } + if constexpr (Flag::Unit == DAY) { + diff = ts_arg.daynr() - ts_origin.daynr(); + trivial_part_ts_arg = nanos_since_midnight(ts_arg); + trivial_part_ts_res = nanos_since_midnight(ts_origin); + } + if constexpr (Flag::Unit == HOUR) { + diff = (ts_arg.daynr() - ts_origin.daynr()) * HOUR_PER_DAY + ts_arg.hour() - + ts_origin.hour(); + trivial_part_ts_arg = (ts_arg.minute() * SECOND_PER_MINUTE + ts_arg.second()) * + TimeStampNsValue::NANOS_PER_SECOND + + ts_arg.nanosecond(); + trivial_part_ts_res = + (ts_origin.minute() * SECOND_PER_MINUTE + ts_origin.second()) * + TimeStampNsValue::NANOS_PER_SECOND + + ts_origin.nanosecond(); + } + if constexpr (Flag::Unit == MINUTE) { + diff = (ts_arg.daynr() - ts_origin.daynr()) * HOUR_PER_DAY * SECOND_PER_MINUTE + + (ts_arg.hour() - ts_origin.hour()) * SECOND_PER_MINUTE + ts_arg.minute() - + ts_origin.minute(); + trivial_part_ts_arg = + ts_arg.second() * TimeStampNsValue::NANOS_PER_SECOND + ts_arg.nanosecond(); + trivial_part_ts_res = ts_origin.second() * TimeStampNsValue::NANOS_PER_SECOND + + ts_origin.nanosecond(); + } + if constexpr (Flag::Unit == SECOND) { + diff = ts_arg.datetime_diff_in_seconds(ts_origin); + trivial_part_ts_arg = ts_arg.nanosecond(); + trivial_part_ts_res = ts_origin.nanosecond(); + } } //round down/up to specific time-unit(HOUR/DAY/MONTH...) by increase/decrease diff variable @@ -785,6 +870,10 @@ struct DateTimeFloorCeilCore { /// optimized path constexpr static bool can_use_optimize(int period) { + if constexpr (std::is_same_v) { + return false; + } + // For TimestampTzValue on date-based units, disable optimization to ensure timezone conversion if constexpr (std::is_same_v) { if constexpr (Flag::Unit == YEAR || Flag::Unit == QUARTER || Flag::Unit == MONTH || @@ -926,6 +1015,12 @@ struct DateTimeFloorCeilCore { FunctionDateTimeFloorCeil; \ using FunctionDateTimeV2ThreeArg##IMPL##DELTA = \ FunctionDateTimeFloorCeil; \ + using FunctionTimestampNsOneArg##IMPL##DELTA = \ + FunctionDateTimeFloorCeil; \ + using FunctionTimestampNsTwoArg##IMPL##DELTA = \ + FunctionDateTimeFloorCeil; \ + using FunctionTimestampNsThreeArg##IMPL##DELTA = \ + FunctionDateTimeFloorCeil; \ using FunctionTimestamptzOneArg##IMPL##DELTA = \ FunctionDateTimeFloorCeil; \ using FunctionTimestamptzTwoArg##IMPL##DELTA = \ @@ -944,6 +1039,8 @@ struct DateTimeFloorCeilCore { using FunctionDateV2TwoArg##IMPL = FunctionDateTimeFloorCeil; \ using FunctionDateTimeV2TwoArg##IMPL = \ FunctionDateTimeFloorCeil; \ + using FunctionTimestampNsTwoArg##IMPL = \ + FunctionDateTimeFloorCeil; \ using FunctionTimestamptzTwoArg##IMPL = \ FunctionDateTimeFloorCeil; @@ -973,10 +1070,14 @@ void register_function_datetime_floor_ceil(SimpleFunctionFactory& factory) { factory.register_function(); \ factory.register_function(); \ factory.register_function(); \ + factory.register_function(); \ + factory.register_function(); \ + factory.register_function(); \ factory.register_function(); \ factory.register_function(); \ factory.register_function(); \ factory.register_function(); \ + factory.register_function(); \ factory.register_function(); \ factory.register_function(); diff --git a/be/src/exprs/function/function_datetime_string_to_string.cpp b/be/src/exprs/function/function_datetime_string_to_string.cpp index 9fca37931ecc84..b6fc3183f27ac6 100644 --- a/be/src/exprs/function/function_datetime_string_to_string.cpp +++ b/be/src/exprs/function/function_datetime_string_to_string.cpp @@ -27,6 +27,8 @@ namespace doris { using FunctionDateFormatV2 = FunctionDateTimeStringToString>; using FunctionDateTimeV2DateFormat = FunctionDateTimeStringToString>; +using FunctionTimestampNsDateFormat = + FunctionDateTimeStringToString>; // old version using FunctionFromUnixTimeOneArg = FunctionDateTimeStringToString>; using FunctionFromUnixTimeTwoArg = FunctionDateTimeStringToString>; @@ -39,6 +41,7 @@ using FunctionFromUnixTimeNewDecimalTwoArg = FunctionDateTimeStringToString>; using FunctionTimeFormatDate = FunctionTimeFormat; using FunctionTimeFormatDateTime = FunctionTimeFormat; +using FunctionTimeFormatTimeStampNs = FunctionTimeFormat; using FunctionTimeFormatTime = FunctionTimeFormat; void register_function_date_time_string_to_string(SimpleFunctionFactory& factory) { @@ -50,8 +53,10 @@ void register_function_date_time_string_to_string(SimpleFunctionFactory& factory factory.register_function(); factory.register_function(); factory.register_function(); + factory.register_function(); factory.register_function(); factory.register_function(); + factory.register_function(); factory.register_function(); } diff --git a/be/src/exprs/function/function_datetime_string_to_string.h b/be/src/exprs/function/function_datetime_string_to_string.h index f927389ac261d5..c1d7071fdb938d 100644 --- a/be/src/exprs/function/function_datetime_string_to_string.h +++ b/be/src/exprs/function/function_datetime_string_to_string.h @@ -229,6 +229,7 @@ class FunctionDateTimeStringToString : public IFunction { std::is_same_v || std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v) { char buf[64]; pod_array[i].to_string(buf); diff --git a/be/src/exprs/function/function_map.cpp b/be/src/exprs/function/function_map.cpp index e0b06e7450dfb3..4f9af19cd86978 100644 --- a/be/src/exprs/function/function_map.cpp +++ b/be/src/exprs/function/function_map.cpp @@ -566,7 +566,9 @@ class FunctionMapContainsEntry : public IFunction { return true; }; - if (!dispatch_switch_all(type, call)) { + if (type == TYPE_TIMESTAMP_NS) { + call(DispatchDataType()); + } else if (!dispatch_switch_all(type, call)) { throw doris::Exception(ErrorCode::INTERNAL_ERROR, "not support type {}", type_to_string(type)); } @@ -755,11 +757,11 @@ class FunctionMapContainsEntry : public IFunction { /*nan_direction_hint=*/1) == 0; } - // whether this function supports equality comparison for the given primitive type. - // Uses dispatch_switch_all as the single source of truth so any type supported - // by the dispatch layer is automatically accepted here. + // TIMESTAMP_NS is dispatched locally because adding it to the shared scalar + // dispatcher would instantiate unrelated arithmetic-only templates for this type. bool is_equality_comparison_supported(PrimitiveType type) const { - return dispatch_switch_all(type, [](const auto&) { return true; }); + return type == TYPE_TIMESTAMP_NS || + dispatch_switch_all(type, [](const auto&) { return true; }); } }; diff --git a/be/src/exprs/function/function_other_types_to_date.cpp b/be/src/exprs/function/function_other_types_to_date.cpp index 122fdb9338ad57..b10e791317c641 100644 --- a/be/src/exprs/function/function_other_types_to_date.cpp +++ b/be/src/exprs/function/function_other_types_to_date.cpp @@ -540,8 +540,9 @@ struct DateTrunc { auto& res = result_column.get_data(); for (size_t i = 0; i < input_rows_count; ++i) { auto dt = data[i]; - // datetime_trunc only raise only when dt invalid which is impossible. so we dont throw error better. - // then we can use default implementation for nulls with no worry of invalid nested value. + // TimestampTz truncation is evaluated in the session time zone. Other date values use + // their civil representation directly; nano values may additionally fail when the + // truncated result is outside the signed epoch-nanosecond range. if constexpr (PType == TYPE_TIMESTAMPTZ) { DateV2Value local_dt; dt.convert_utc_to_local(timezone, local_dt); @@ -554,7 +555,13 @@ struct DateTrunc { dt.convert_local_to_utc(timezone, local_dt); } } else { - dt.template datetime_trunc(); + if constexpr (PType == TYPE_TIMESTAMP_NS) { + if (!dt.template datetime_trunc()) { + throw_out_of_bound_one_date("date_trunc", data[i]); + } + } else { + dt.template datetime_trunc(); + } } res[i] = dt; } @@ -695,15 +702,18 @@ template struct UnixTimeStampDateImpl { static DataTypes get_variadic_argument_types() { return {std::make_shared()}; } - using ResultDataType = + using ResultDataType = std::conditional_t< + std::is_same_v, DataTypeDecimal128, std::conditional_t, DataTypeDecimal64, - std::conditional_t>; - using ResultColumnType = + std::conditional_t>>; + using ResultColumnType = std::conditional_t< + std::is_same_v, ColumnDecimal128V3, std::conditional_t, ColumnDecimal64, - std::conditional_t>; + std::conditional_t>>; static DataTypePtr get_return_type_impl(const ColumnsWithTypeAndName& arguments) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || + std::is_same_v) { UInt32 scale = arguments[0].type->get_scale(); return std::make_shared(12 + scale, scale); } else { @@ -711,6 +721,9 @@ struct UnixTimeStampDateImpl { } } + // The compile-time branches keep the four date storage representations type-safe and avoid + // runtime type dispatch in this hot path. + // NOLINTNEXTLINE(readability-function-size) static Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, uint32_t result, size_t input_rows_count) { @@ -747,7 +760,7 @@ struct UnixTimeStampDateImpl { col_result_data[i] = trim_timestamp(timestamp, NewVersion); } block.replace_by_position(result, std::move(col_result)); - } else { // DatetimeV2 + } else if constexpr (std::is_same_v) { const auto* col_source = assert_cast(col.get()); UInt32 scale = block.get_by_position(arguments[0]).type->get_scale(); auto col_result = ColumnDecimal64::create(input_rows_count, scale); @@ -768,6 +781,30 @@ struct UnixTimeStampDateImpl { .value; } block.replace_by_position(result, std::move(col_result)); + } else { + const auto* col_source = assert_cast(col.get()); + UInt32 scale = block.get_by_position(arguments[0]).type->get_scale(); + auto col_result = ColumnDecimal128V3::create(input_rows_count, scale); + auto& col_result_data = col_result->get_data(); + col_result->resize(input_rows_count); + const Int128 scale_multiplier = common::exp10_i128(scale); + + for (int i = 0; i < input_rows_count; i++) { + const auto& value = col_source->get_data()[i]; + auto datetime = value.to_datetime(); + int64_t timestamp = 0; + datetime.unix_timestamp(×tamp, context->state()->timezone_obj()); + const int64_t original_timestamp = timestamp; + timestamp = trim_timestamp(timestamp, NewVersion); + if (timestamp == 0 && original_timestamp != 0) { + col_result_data[i] = Decimal128V3(0); + continue; + } + const Int128 fraction = value.nanosecond() / common::exp10_i64(9 - scale); + col_result_data[i] = + Decimal128V3(static_cast(timestamp) * scale_multiplier + fraction); + } + block.replace_by_position(result, std::move(col_result)); } return Status::OK(); @@ -940,18 +977,25 @@ struct Sec { static constexpr auto name = "second_timestamp"; static constexpr Int64 ratio = 1; }; -template +template class DateTimeToTimestamp : public IFunction { public: + static_assert(PType == TYPE_DATETIMEV2 || PType == TYPE_TIMESTAMP_NS); using ReturnType = Int64; static constexpr Int64 ratio_to_micro = (1000 * 1000) / Impl::ratio; static constexpr auto name = Impl::name; - static FunctionPtr create() { return std::make_shared>(); } + static FunctionPtr create() { return std::make_shared>(); } String get_name() const override { return name; } size_t get_number_of_arguments() const override { return 1; } + bool is_variadic() const override { return true; } + + DataTypes get_variadic_argument_types_impl() const override { + return {std::make_shared::DataType>()}; + } + DataTypePtr get_return_type_impl(const ColumnsWithTypeAndName& arguments) const override { if (arguments[0].type->is_nullable()) { return make_nullable(std::make_shared()); @@ -962,18 +1006,22 @@ class DateTimeToTimestamp : public IFunction { Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, uint32_t result, size_t input_rows_count) const override { const auto& arg_col = block.get_by_position(arguments[0]).column; - const auto& column_data = assert_cast(*arg_col); + const auto& column_data = assert_cast&>(*arg_col); auto res_col = ColumnInt64::create(); auto& res_data = res_col->get_data(); res_col->get_data().resize_fill(input_rows_count, 0); for (int i = 0; i < input_rows_count; i++) { - StringRef source = column_data.get_data_at(i); - const auto& dt = - reinterpret_cast&>(*source.data); + const auto& source = column_data.get_data()[i]; + DateV2Value dt; + if constexpr (PType == TYPE_TIMESTAMP_NS) { + dt = source.to_datetime(); + } else { + dt = source; + } const cctz::time_zone& time_zone = context->state()->timezone_obj(); int64_t timestamp {0}; dt.unix_timestamp(×tamp, time_zone); - auto microsecond = dt.microsecond(); + auto microsecond = source.microsecond(); timestamp = timestamp * Impl::ratio + microsecond / ratio_to_micro; res_data[i] = timestamp; } @@ -1075,14 +1123,15 @@ struct LastDayImpl { throw_out_of_bound_one_date("last_day", cur_data); } int day = get_last_month_day(ts_value.year(), ts_value.month()); - // day is definitely legal if constexpr (std::is_same_v) { ts_value.template unchecked_set_time_unit(day); res_data[i] = ts_value; - } else { // datetimev2 + } else if constexpr (std::is_same_v) { ts_value.template unchecked_set_time_unit(day); ts_value.unchecked_set_time(ts_value.year(), ts_value.month(), day, 0, 0, 0, 0); DataTypeDateTimeV2::cast_to_date_v2(ts_value, res_data[i]); + } else { + res_data[i].unchecked_set_time(ts_value.year(), ts_value.month(), day, 0, 0, 0, 0); } } } @@ -1153,20 +1202,17 @@ struct ToMondayImpl { res_data[i] = ts_value; continue; } - - // day_of_week, from 1(Mon) to 7(Sun) int day_of_week = ts_value.weekday() + 1; int gap_of_monday = day_of_week - 1; TimeInterval interval(DAY, gap_of_monday, true); ts_value.template date_add_interval(interval); res_data[i] = ts_value; - } else { // datetimev2 + } else if constexpr (std::is_same_v) { if (is_special_day(ts_value.year(), ts_value.month(), ts_value.day())) { ts_value.unchecked_set_time(ts_value.year(), ts_value.month(), 1, 0, 0, 0, 0); DataTypeDateTimeV2::cast_to_date_v2(ts_value, res_data[i]); continue; } - // day_of_week, from 1(Mon) to 7(Sun) int day_of_week = ts_value.weekday() + 1; int gap_of_monday = day_of_week - 1; TimeInterval interval(DAY, gap_of_monday, true); @@ -1174,6 +1220,17 @@ struct ToMondayImpl { ts_value.unchecked_set_time(ts_value.year(), ts_value.month(), ts_value.day(), 0, 0, 0, 0); DataTypeDateTimeV2::cast_to_date_v2(ts_value, res_data[i]); + } else { + if (is_special_day(ts_value.year(), ts_value.month(), ts_value.day())) { + res_data[i].unchecked_set_time(ts_value.year(), ts_value.month(), 1, 0, 0, 0, + 0); + continue; + } + int day_of_week = ts_value.weekday() + 1; + int gap_of_monday = day_of_week - 1; + if (!res_data[i].get_date_from_daynr(ts_value.daynr() - gap_of_monday)) { + throw_out_of_bound_one_date("to_monday", cur_data); + } } } } @@ -1224,9 +1281,11 @@ class FunctionOtherTypesToDateType : public IFunction { Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override { if constexpr (std::is_same_v> || std::is_same_v> || + std::is_same_v> || std::is_same_v> || std::is_same_v> || std::is_same_v> || + std::is_same_v> || std::is_same_v>) { return Impl::open(context, scope); } else { @@ -1474,12 +1533,16 @@ using FunctionMakeDate = FunctionOtherTypesToDateType; using FunctionDateTruncDateV2 = FunctionOtherTypesToDateType>; using FunctionDateTruncDatetimeV2 = FunctionOtherTypesToDateType>; +using FunctionDateTruncTimestampNs = + FunctionOtherTypesToDateType>; using FunctionDateTruncTimestamptz = FunctionOtherTypesToDateType>; using FunctionDateTruncDateV2WithCommonOrder = FunctionOtherTypesToDateType>; using FunctionDateTruncDatetimeV2WithCommonOrder = FunctionOtherTypesToDateType>; +using FunctionDateTruncTimestampNsWithCommonOrder = + FunctionOtherTypesToDateType>; using FunctionDateTruncTimestamptzWithCommonOrder = FunctionOtherTypesToDateType>; using FunctionFromIso8601DateV2 = FunctionOtherTypesToDateType; @@ -1492,9 +1555,11 @@ void register_function_timestamp(SimpleFunctionFactory& factory) { factory.register_function(); factory.register_function(); factory.register_function(); + factory.register_function(); factory.register_function(); factory.register_function(); factory.register_function(); + factory.register_function(); factory.register_function(); factory.register_function(); @@ -1503,6 +1568,7 @@ void register_function_timestamp(SimpleFunctionFactory& factory) { factory.register_function>>(); factory.register_function>>(); factory.register_function>>(); + factory.register_function>>(); factory.register_function>>(); factory.register_function>>(); factory.register_function< @@ -1513,16 +1579,23 @@ void register_function_timestamp(SimpleFunctionFactory& factory) { FunctionUnixTimestampNew>>(); factory.register_function< FunctionUnixTimestampNew>>(); + factory.register_function< + FunctionUnixTimestampNew>>(); factory.register_function>>(); factory.register_function>(); factory.register_function>(); + factory.register_function>(); factory.register_function>(); factory.register_function>(); - - factory.register_function>(); - factory.register_function>(); - factory.register_function>(); + factory.register_function>(); + + factory.register_function>(); + factory.register_function>(); + factory.register_function>(); + factory.register_function>(); + factory.register_function>(); + factory.register_function>(); } #include "common/compile_check_avoid_end.h" } // namespace doris diff --git a/be/src/exprs/function/function_width_bucket.cpp b/be/src/exprs/function/function_width_bucket.cpp index f9660551b99580..ee0fcf26681627 100644 --- a/be/src/exprs/function/function_width_bucket.cpp +++ b/be/src/exprs/function/function_width_bucket.cpp @@ -123,6 +123,35 @@ class FunctionWidthBucket : public IFunction { } } + void _execute_timestamp_ns(const IColumn& expr_column, const IColumn& min_value_column, + const IColumn& max_value_column, const int64_t num_buckets, + ColumnInt64::MutablePtr& nested_column) const { + const auto& expr_data = assert_cast(expr_column).get_data(); + const auto& min_value_data = + assert_cast(min_value_column).get_data(); + const auto& max_value_data = + assert_cast(max_value_column).get_data(); + auto& nested_data = nested_column->get_data(); + + for (size_t i = 0; i < expr_data.size(); ++i) { + const int64_t expr = expr_data[i].epoch_nanos(); + const int64_t min_value = min_value_data[i].epoch_nanos(); + const int64_t max_value = max_value_data[i].epoch_nanos(); + if (expr < min_value) { + continue; + } else if (expr >= max_value) { + nested_data[i] = num_buckets + 1; + } else { + const auto range = static_cast<__int128>(max_value) - min_value; + if (range / num_buckets == 0) { + continue; + } + const auto offset = static_cast<__int128>(expr) - min_value; + nested_data[i] = static_cast(1 + offset * num_buckets / range); + } + } + } + bool _execute_by_type(const IColumn& expr_column, const IColumn& min_value_column, const IColumn& max_value_column, const int64_t num_buckets, ColumnInt64::MutablePtr& nested_column_column, @@ -152,6 +181,10 @@ class FunctionWidthBucket : public IFunction { _execute(expr_column, min_value_column, max_value_column, num_buckets, nested_column_column); break; + case PrimitiveType::TYPE_TIMESTAMP_NS: + _execute_timestamp_ns(expr_column, min_value_column, max_value_column, num_buckets, + nested_column_column); + break; default: return false; break; diff --git a/be/src/exprs/function/functions_comparison.h b/be/src/exprs/function/functions_comparison.h index a0789c259c790b..e6aa5350de9246 100644 --- a/be/src/exprs/function/functions_comparison.h +++ b/be/src/exprs/function/functions_comparison.h @@ -777,7 +777,8 @@ class FunctionComparison : public IFunction { } auto can_compare = [](PrimitiveType t) -> bool { - return is_int_or_bool(t) || is_float_or_double(t) || is_ip(t) || is_date_type(t); + return is_int_or_bool(t) || is_float_or_double(t) || is_ip(t) || is_date_type(t) || + is_timestamp_ns_type(t); }; if (can_compare(left_type->get_primitive_type()) && @@ -798,6 +799,8 @@ class FunctionComparison : public IFunction { return execute_num_type(block, result, col_left_ptr, col_right_ptr); case TYPE_DATETIMEV2: return execute_num_type(block, result, col_left_ptr, col_right_ptr); + case TYPE_TIMESTAMP_NS: + return execute_num_type(block, result, col_left_ptr, col_right_ptr); case TYPE_TIMESTAMPTZ: return execute_num_type(block, result, col_left_ptr, col_right_ptr); case TYPE_TINYINT: diff --git a/be/src/exprs/function/least_greast.cpp b/be/src/exprs/function/least_greast.cpp index 13558035636154..d8005d3df7a545 100644 --- a/be/src/exprs/function/least_greast.cpp +++ b/be/src/exprs/function/least_greast.cpp @@ -113,7 +113,13 @@ struct CompareMultiImpl { return true; }; - if (!dispatch_switch_scalar(data_type->get_primitive_type(), call)) { + bool supported = false; + if (data_type->get_primitive_type() == TYPE_TIMESTAMP_NS) { + supported = call(DispatchDataType()); + } else { + supported = dispatch_switch_scalar(data_type->get_primitive_type(), call); + } + if (!supported) { throw doris::Exception(ErrorCode::INTERNAL_ERROR, "not support type {}", data_type->get_name()); } @@ -304,6 +310,13 @@ struct FunctionFieldImpl { } break; } + case PrimitiveType::TYPE_TIMESTAMP_NS: { + for (int col = 1; col < arguments.size(); ++col) { + insert_result_data(res_data, argument_columns[0], + argument_columns[col], input_rows_count, col); + } + break; + } case PrimitiveType::TYPE_TIMESTAMPTZ: { for (int col = 1; col < arguments.size(); ++col) { insert_result_data(res_data, argument_columns[0], @@ -367,4 +380,4 @@ void register_function_least_greast(SimpleFunctionFactory& factory) { factory.register_function(); factory.register_function(); } -}; // namespace doris \ No newline at end of file +}; // namespace doris diff --git a/be/src/exprs/function/time_of_function.cpp b/be/src/exprs/function/time_of_function.cpp index 6162477f38517f..5a1bf52cfca14d 100644 --- a/be/src/exprs/function/time_of_function.cpp +++ b/be/src/exprs/function/time_of_function.cpp @@ -51,6 +51,19 @@ using FunctionDateTimeV2YearWeek = using FunctionDateTimeV2WeekDay = FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsWeekOfYear = + FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsDayOfYear = + FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsDayOfWeek = + FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsDayOfMonth = + FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsYearWeek = + FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsWeekDay = + FunctionDateOrDateTimeToSomething>; + void register_function_time_of_function(SimpleFunctionFactory& factory) { factory.register_function(); factory.register_function(); @@ -64,5 +77,11 @@ void register_function_time_of_function(SimpleFunctionFactory& factory) { factory.register_function(); factory.register_function(); factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); } } // namespace doris diff --git a/be/src/exprs/function/to_time_function.cpp b/be/src/exprs/function/to_time_function.cpp index 2f4b6491ceb4d2..f3bf9b85fc3b21 100644 --- a/be/src/exprs/function/to_time_function.cpp +++ b/be/src/exprs/function/to_time_function.cpp @@ -72,6 +72,38 @@ using FunctionCenturyV2 = FunctionDateOrDateTimeToSomething>; using FunctionDateTimeV2Century = FunctionDateOrDateTimeToSomething>; + +using FunctionTimestampNsYear = + FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsQuarter = + FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsMonth = + FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsDay = + FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsWeek = + FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsHour = + FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsMinute = + FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsSecond = + FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsToDays = + FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsMicroSecond = + FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsToDate = + FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsDate = + FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsTimestamp = + FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsCentury = + FunctionDateOrDateTimeToSomething>; +using FunctionTimestampNsToSeconds = + FunctionDateOrDateTimeToSomething>; + void register_function_to_time_function(SimpleFunctionFactory& factory) { factory.register_function(); factory.register_function(); @@ -100,6 +132,21 @@ void register_function_to_time_function(SimpleFunctionFactory& factory) { factory.register_function(); factory.register_function(); factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); factory.register_alias("date", "datev2"); factory.register_alias("to_date", "to_datev2"); } diff --git a/be/src/exprs/lambda_function/varray_sort_function.cpp b/be/src/exprs/lambda_function/varray_sort_function.cpp index dfd2ed1a8ae58e..2d0484c64f07a7 100644 --- a/be/src/exprs/lambda_function/varray_sort_function.cpp +++ b/be/src/exprs/lambda_function/varray_sort_function.cpp @@ -52,7 +52,7 @@ using ConstColumnVariant = const ColumnDecimal32*, const ColumnDecimal64*, const ColumnDecimal128V2*, const ColumnDecimal128V3*, const ColumnDecimal256*, const ColumnDate*, const ColumnDateTime*, const ColumnDateV2*, const ColumnDateTimeV2*, - const ColumnTimeV2*>; + const ColumnTimeStampNs*, const ColumnTimeV2*>; template struct is_column_vector : std::false_type {}; @@ -422,6 +422,7 @@ class ArraySortFunction : public LambdaFunction { DISPATCH_PRIMITIVE_TYPE(TYPE_DATETIME, ColumnDateTime) DISPATCH_PRIMITIVE_TYPE(TYPE_DATEV2, ColumnDateV2) DISPATCH_PRIMITIVE_TYPE(TYPE_DATETIMEV2, ColumnDateTimeV2) + DISPATCH_PRIMITIVE_TYPE(TYPE_TIMESTAMP_NS, ColumnTimeStampNs) DISPATCH_PRIMITIVE_TYPE(TYPE_TIMEV2, ColumnTimeV2) default: return Status::InternalError("Unsupported type in array_sort"); diff --git a/be/src/exprs/vcase_expr.h b/be/src/exprs/vcase_expr.h index 07793b969e019f..d1312cb4983c3a 100644 --- a/be/src/exprs/vcase_expr.h +++ b/be/src/exprs/vcase_expr.h @@ -143,6 +143,7 @@ class VCaseExpr final : public VExpr { CASE_TYPE(TYPE_DATETIME, ColumnDateTime) CASE_TYPE(TYPE_DATEV2, ColumnDateV2) CASE_TYPE(TYPE_DATETIMEV2, ColumnDateTimeV2) + CASE_TYPE(TYPE_TIMESTAMP_NS, ColumnTimeStampNs) CASE_TYPE(TYPE_TIMESTAMPTZ, ColumnTimeStampTz) CASE_TYPE(TYPE_IPV6, ColumnIPv6) CASE_TYPE(TYPE_IPV4, ColumnIPv4) @@ -231,6 +232,7 @@ class VCaseExpr final : public VExpr { std::is_same_v || std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v) { result_raw_data[i] = ColumnType::default_value(); } else { @@ -251,6 +253,7 @@ class VCaseExpr final : public VExpr { std::is_same_v || std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v) { for (int row_idx = 0; row_idx < rows_count; row_idx++) { result_raw_data[row_idx] = (then_idx[row_idx] == i) ? column_raw_data[row_idx] diff --git a/be/src/exprs/vcondition_expr.cpp b/be/src/exprs/vcondition_expr.cpp index 0f9d8e6a7bd427..dc0bf671e53530 100644 --- a/be/src/exprs/vcondition_expr.cpp +++ b/be/src/exprs/vcondition_expr.cpp @@ -577,6 +577,11 @@ void insert_result_data(MutableColumnPtr& result_column, ColumnPtr& argument_col result_raw_data[row].to_date_int_val() + column_raw_data[row].to_date_int_val() * uint64_t(!(null_map_data[row] | filled_flag[row]))); + } else if constexpr (std::is_same_v) { + result_raw_data[row] = + TimeStampNsValue(result_raw_data[row].epoch_nanos() + + column_raw_data[row].epoch_nanos() * + int64_t(!(null_map_data[row] | filled_flag[row]))); } else if constexpr (std::is_same_v) { result_raw_data[row] = binary_cast( result_raw_data[row].to_date_int_val() + diff --git a/be/src/exprs/vdirect_in_predicate.h b/be/src/exprs/vdirect_in_predicate.h index 693571d25bf777..5a71294ddb42a2 100644 --- a/be/src/exprs/vdirect_in_predicate.h +++ b/be/src/exprs/vdirect_in_predicate.h @@ -264,6 +264,7 @@ class VDirectInPredicate final : public VExpr { RETURN_RAW_FIXED_SIZE(TYPE_DATETIME); RETURN_RAW_FIXED_SIZE(TYPE_DATEV2); RETURN_RAW_FIXED_SIZE(TYPE_DATETIMEV2); + RETURN_RAW_FIXED_SIZE(TYPE_TIMESTAMP_NS); RETURN_RAW_FIXED_SIZE(TYPE_TIMESTAMPTZ); RETURN_RAW_FIXED_SIZE(TYPE_TIMEV2); RETURN_RAW_FIXED_SIZE(TYPE_DECIMAL32); diff --git a/be/src/exprs/vectorized_fn_call.cpp b/be/src/exprs/vectorized_fn_call.cpp index 6e9f25be48d864..d88ac5a587a3c3 100644 --- a/be/src/exprs/vectorized_fn_call.cpp +++ b/be/src/exprs/vectorized_fn_call.cpp @@ -197,6 +197,7 @@ size_t raw_comparison_value_size(PrimitiveType primitive_type) { RETURN_RAW_COMPARISON_SIZE(TYPE_DATETIME); RETURN_RAW_COMPARISON_SIZE(TYPE_DATEV2); RETURN_RAW_COMPARISON_SIZE(TYPE_DATETIMEV2); + RETURN_RAW_COMPARISON_SIZE(TYPE_TIMESTAMP_NS); RETURN_RAW_COMPARISON_SIZE(TYPE_TIMESTAMPTZ); RETURN_RAW_COMPARISON_SIZE(TYPE_TIMEV2); RETURN_RAW_COMPARISON_SIZE(TYPE_DECIMAL32); @@ -542,6 +543,7 @@ Status VectorizedFnCall::execute_on_raw_fixed_values(const uint8_t* values, size EXECUTE_RAW_SCALAR_COMPARISON(TYPE_DATETIME); EXECUTE_RAW_SCALAR_COMPARISON(TYPE_DATEV2); EXECUTE_RAW_SCALAR_COMPARISON(TYPE_DATETIMEV2); + EXECUTE_RAW_SCALAR_COMPARISON(TYPE_TIMESTAMP_NS); EXECUTE_RAW_SCALAR_COMPARISON(TYPE_TIMESTAMPTZ); EXECUTE_RAW_SCALAR_COMPARISON(TYPE_TIMEV2); EXECUTE_RAW_SCALAR_COMPARISON(TYPE_DECIMAL32); diff --git a/be/src/exprs/vexpr.cpp b/be/src/exprs/vexpr.cpp index 5b1f835ace5a26..1aca5f8a3cae1f 100644 --- a/be/src/exprs/vexpr.cpp +++ b/be/src/exprs/vexpr.cpp @@ -138,6 +138,10 @@ TExprNode create_texpr_node_from(const void* data, const PrimitiveType& type, in THROW_IF_ERROR(create_texpr_literal_node(data, &node, precision, scale)); break; } + case TYPE_TIMESTAMP_NS: { + THROW_IF_ERROR(create_texpr_literal_node(data, &node)); + break; + } case TYPE_DATE: { THROW_IF_ERROR(create_texpr_literal_node(data, &node)); break; @@ -261,6 +265,11 @@ TExprNode create_texpr_node_from(const Field& field, const PrimitiveType& type, create_texpr_literal_node(&storage, &node, precision, scale)); break; } + case TYPE_TIMESTAMP_NS: { + const auto& storage = field.get(); + THROW_IF_ERROR(create_texpr_literal_node(&storage, &node)); + break; + } case TYPE_TIMESTAMPTZ: { const auto& storage = field.get(); diff --git a/be/src/exprs/vexpr.h b/be/src/exprs/vexpr.h index c0b99ab7a8f4dc..2c015787adcd39 100644 --- a/be/src/exprs/vexpr.h +++ b/be/src/exprs/vexpr.h @@ -612,6 +612,15 @@ Status create_texpr_literal_node(const void* data, TExprNode* node, int precisio (*node).__set_date_literal(date_literal); (*node).__set_node_type(TExprNodeType::DATE_LITERAL); (*node).__set_type(create_type_desc(PrimitiveType::TYPE_DATETIMEV2, precision, scale)); + } else if constexpr (T == TYPE_TIMESTAMP_NS) { + const auto* origin_value = reinterpret_cast(data); + TDateLiteral date_literal; + char convert_buffer[30]; + origin_value->to_string(convert_buffer); + date_literal.__set_value(convert_buffer); + (*node).__set_date_literal(date_literal); + (*node).__set_node_type(TExprNodeType::DATE_LITERAL); + (*node).__set_type(create_type_desc(PrimitiveType::TYPE_TIMESTAMP_NS)); } else if constexpr (T == TYPE_TIMESTAMPTZ) { const auto* origin_value = reinterpret_cast(data); TDateLiteral date_literal; diff --git a/be/src/exprs/vin_predicate.cpp b/be/src/exprs/vin_predicate.cpp index 0dbfb3f7e9a289..61bd18f2f8b1c8 100644 --- a/be/src/exprs/vin_predicate.cpp +++ b/be/src/exprs/vin_predicate.cpp @@ -64,6 +64,7 @@ size_t raw_in_value_size(PrimitiveType primitive_type) { RETURN_RAW_IN_SIZE(TYPE_DATETIME); RETURN_RAW_IN_SIZE(TYPE_DATEV2); RETURN_RAW_IN_SIZE(TYPE_DATETIMEV2); + RETURN_RAW_IN_SIZE(TYPE_TIMESTAMP_NS); RETURN_RAW_IN_SIZE(TYPE_TIMESTAMPTZ); RETURN_RAW_IN_SIZE(TYPE_TIMEV2); RETURN_RAW_IN_SIZE(TYPE_DECIMAL32); diff --git a/be/src/exprs/vtopn_pred.cpp b/be/src/exprs/vtopn_pred.cpp index cc26b6679a1342..07211dc1916a89 100644 --- a/be/src/exprs/vtopn_pred.cpp +++ b/be/src/exprs/vtopn_pred.cpp @@ -45,6 +45,7 @@ size_t topn_raw_value_size(PrimitiveType type) { RETURN_TOPN_RAW_SIZE(TYPE_DATETIME); RETURN_TOPN_RAW_SIZE(TYPE_DATEV2); RETURN_TOPN_RAW_SIZE(TYPE_DATETIMEV2); + RETURN_TOPN_RAW_SIZE(TYPE_TIMESTAMP_NS); RETURN_TOPN_RAW_SIZE(TYPE_TIMESTAMPTZ); // Master no longer defines a C++ carrier for legacy TYPE_TIME; Parquet time values use // TYPE_TIMEV2, so advertising the deprecated tag would make direct filtering unusable. @@ -160,6 +161,7 @@ Status VTopNPred::execute_on_raw_fixed_values(const uint8_t* values, size_t num_ EXECUTE_TOPN_RAW_SCALAR(TYPE_DATETIME); EXECUTE_TOPN_RAW_SCALAR(TYPE_DATEV2); EXECUTE_TOPN_RAW_SCALAR(TYPE_DATETIMEV2); + EXECUTE_TOPN_RAW_SCALAR(TYPE_TIMESTAMP_NS); EXECUTE_TOPN_RAW_SCALAR(TYPE_TIMESTAMPTZ); // Keep dispatch aligned with topn_raw_value_size(): legacy TYPE_TIME has no master carrier. EXECUTE_TOPN_RAW_SCALAR(TYPE_TIMEV2); diff --git a/be/src/format/arrow/arrow_row_batch.cpp b/be/src/format/arrow/arrow_row_batch.cpp index 9c8e94e10c4103..8bd2789bbb78eb 100644 --- a/be/src/format/arrow/arrow_row_batch.cpp +++ b/be/src/format/arrow/arrow_row_batch.cpp @@ -48,6 +48,8 @@ namespace doris { +// Keep the Doris-to-Arrow primitive type matrix centralized so every output path shares it. +// NOLINTNEXTLINE(readability-function-size) Status convert_to_arrow_type(const DataTypePtr& origin_type, std::shared_ptr* result, const std::string& timezone) { @@ -97,6 +99,9 @@ Status convert_to_arrow_type(const DataTypePtr& origin_type, case TYPE_DATEV2: *result = std::make_shared(); break; + case TYPE_TIMESTAMP_NS: + *result = std::make_shared(arrow::TimeUnit::NANO, timezone); + break; // TODO: maybe need to distinguish TYPE_DATETIME and TYPE_TIMESTAMPTZ case TYPE_TIMESTAMPTZ: case TYPE_DATETIMEV2: diff --git a/be/src/format/jni/jni_data_bridge.cpp b/be/src/format/jni/jni_data_bridge.cpp index 9dc935e0b62da5..a4edaeecf21291 100644 --- a/be/src/format/jni/jni_data_bridge.cpp +++ b/be/src/format/jni/jni_data_bridge.cpp @@ -60,6 +60,7 @@ namespace doris { M(PrimitiveType::TYPE_DATEV2, ColumnDateV2, UInt32) \ M(PrimitiveType::TYPE_DATETIME, ColumnDateTime, Int64) \ M(PrimitiveType::TYPE_DATETIMEV2, ColumnDateTimeV2, UInt64) \ + M(PrimitiveType::TYPE_TIMESTAMP_NS, ColumnTimeStampNs, Int64) \ M(PrimitiveType::TYPE_TIMESTAMPTZ, ColumnTimeStampTz, UInt64) \ M(PrimitiveType::TYPE_IPV4, ColumnIPv4, IPv4) \ M(PrimitiveType::TYPE_IPV6, ColumnIPv6, IPv6) @@ -268,6 +269,8 @@ Status JniDataBridge::_fill_struct_column(TableMetaAddress& address, MutableColu return Status::OK(); } +// Keep the JNI type protocol mapping centralized and symmetric with Java ColumnType parsing. +// NOLINTNEXTLINE(readability-function-size) std::string JniDataBridge::get_jni_type(const DataTypePtr& data_type) { DataTypePtr type = remove_nullable(data_type); std::ostringstream buffer; @@ -310,6 +313,8 @@ std::string JniDataBridge::get_jni_type(const DataTypePtr& data_type) { buffer << "datetimev2(" << type->get_scale() << ")"; return buffer.str(); } + case TYPE_TIMESTAMP_NS: + return "timestamp_ns"; case TYPE_TIMESTAMPTZ: { buffer << "timestamptz(" << type->get_scale() << ")"; return buffer.str(); @@ -372,6 +377,8 @@ std::string JniDataBridge::get_jni_type(const DataTypePtr& data_type) { } } +// Keep the alternate string mapping aligned with the primary JNI type protocol mapping. +// NOLINTNEXTLINE(readability-function-size) std::string JniDataBridge::get_jni_type_with_different_string(const DataTypePtr& data_type) { DataTypePtr type = remove_nullable(data_type); std::ostringstream buffer; @@ -414,6 +421,8 @@ std::string JniDataBridge::get_jni_type_with_different_string(const DataTypePtr& buffer << "datetimev2(" << data_type->get_scale() << ")"; return buffer.str(); } + case TYPE_TIMESTAMP_NS: + return "timestamp_ns"; case TYPE_TIMESTAMPTZ: { buffer << "timestamptz(" << data_type->get_scale() << ")"; return buffer.str(); diff --git a/be/src/format/jni/jni_data_bridge.h b/be/src/format/jni/jni_data_bridge.h index e037ffec3d4d5a..be28184dc811d8 100644 --- a/be/src/format/jni/jni_data_bridge.h +++ b/be/src/format/jni/jni_data_bridge.h @@ -176,6 +176,7 @@ class JniDataBridge { !std::is_same_v && !std::is_same_v && !std::is_same_v && + !std::is_same_v && !std::is_same_v) static Status _fill_fixed_length_column(MutableColumnPtr& doris_column, CPP_TYPE* ptr, size_t num_rows) { @@ -188,13 +189,15 @@ class JniDataBridge { template requires(std::is_same_v || - std::is_same_v) + std::is_same_v || + std::is_same_v) static Status _fill_fixed_length_column(MutableColumnPtr& doris_column, CPP_TYPE* ptr, size_t num_rows) { auto& column_data = assert_cast(*doris_column).get_data(); size_t origin_size = column_data.size(); column_data.resize(origin_size + num_rows); - memcpy((int64_t*)column_data.data() + origin_size, ptr, sizeof(CPP_TYPE) * num_rows); + memcpy(reinterpret_cast(column_data.data()) + origin_size, ptr, + sizeof(CPP_TYPE) * num_rows); return Status::OK(); } diff --git a/be/src/format/orc/vorc_reader.cpp b/be/src/format/orc/vorc_reader.cpp index c0bd36ce1eaa6d..55e9bc6ee309c0 100644 --- a/be/src/format/orc/vorc_reader.cpp +++ b/be/src/format/orc/vorc_reader.cpp @@ -850,6 +850,10 @@ std::tuple convert_to_orc_literal(const orc::Type* type, datetime_v2.minute(), datetime_v2.second()); seconds = cctz::convert(civil_seconds, utc0).time_since_epoch().count(); nanos = datetime_v2.microsecond() * 1000; + } else if (primitive_type == TYPE_TIMESTAMP_NS) { + const auto timestamp_ns = *reinterpret_cast(value); + seconds = timestamp_ns.epoch_seconds(); + nanos = static_cast(timestamp_ns.nanosecond()); } else { return std::make_tuple(false, orc::Literal(false)); } @@ -1960,6 +1964,9 @@ Status OrcReader::_fill_doris_data_column(const std::string& col_name, return _decode_time_column, TYPE_DATETIMEV2, orc::TimestampVectorBatch, is_filter>(col_name, data_column, cvb, num_values); + case PrimitiveType::TYPE_TIMESTAMP_NS: + return _decode_time_column(col_name, data_column, cvb, num_values); case PrimitiveType::TYPE_STRING: case PrimitiveType::TYPE_VARCHAR: case PrimitiveType::TYPE_CHAR: @@ -2214,6 +2221,11 @@ Status OrcReader::_orc_column_to_doris_column( MutableColumnPtr data_column; if (orc_column_type != nullptr) { auto src_type = convert_to_doris_type(orc_column_type); + if (remove_nullable(data_type)->get_primitive_type() == TYPE_TIMESTAMP_NS && + (orc_column_type->getKind() == orc::TypeKind::TIMESTAMP || + orc_column_type->getKind() == orc::TypeKind::TIMESTAMP_INSTANT)) { + src_type = DataTypeFactory::instance().create_data_type(TYPE_TIMESTAMP_NS, true); + } bool is_dict_filter_col = false; for (const std::pair& dict_col : _dict_filter_cols) { if (col_name == dict_col.first) { diff --git a/be/src/format/orc/vorc_reader.h b/be/src/format/orc/vorc_reader.h index a20326eed28cf2..289317eafbd03a 100644 --- a/be/src/format/orc/vorc_reader.h +++ b/be/src/format/orc/vorc_reader.h @@ -618,7 +618,28 @@ class OrcReader : public TableFormatReader, public RowPositionProvider { continue; } } - v.from_unixtime(data->data[i], _time_zone); + if constexpr (std::is_same_v) { + const int64_t nanos = data->nanoseconds[i]; + if (nanos < 0 || nanos >= TimeStampNsValue::NANOS_PER_SECOND) { + column_data.resize(origin_size); + return Status::DataQualityError("Invalid ORC timestamp nanoseconds: {}", + nanos); + } + DateV2Value datetime; + datetime.from_unixtime(data->data[i], _time_zone); + datetime.set_microsecond( + static_cast(nanos / TimeStampNsValue::NANOS_PER_MICROSECOND)); + if (!v.from_datetime( + datetime, + static_cast(nanos % + TimeStampNsValue::NANOS_PER_MICROSECOND))) { + column_data.resize(origin_size); + return Status::DataQualityError( + "Decoded ORC timestamp is outside the TIMESTAMP_NS range"); + } + } else { + v.from_unixtime(data->data[i], _time_zone); + } if constexpr (std::is_same_v>) { // nanoseconds will lose precision. only keep microseconds. v.set_microsecond(data->nanoseconds[i] / 1000); diff --git a/be/src/format/parquet/parquet_column_convert.cpp b/be/src/format/parquet/parquet_column_convert.cpp index 8f8a6cc34fcb96..a6e68064491494 100644 --- a/be/src/format/parquet/parquet_column_convert.cpp +++ b/be/src/format/parquet/parquet_column_convert.cpp @@ -270,6 +270,13 @@ std::unique_ptr PhysicalToLogicalConverter::get_conv physical_converter = std::make_unique(src_physical_type, src_logical_type); } + } else if (src_logical_primitive == TYPE_TIMESTAMP_NS) { + if (src_physical_type == tparquet::Type::INT64) { + physical_converter = std::make_unique(); + } else { + physical_converter = + std::make_unique(src_physical_type, src_logical_type); + } } else if (src_logical_primitive == TYPE_VARBINARY) { if (src_physical_type == tparquet::Type::FIXED_LEN_BYTE_ARRAY) { DCHECK(parquet_schema.logicalType.__isset.UUID) << parquet_schema.name; diff --git a/be/src/format/parquet/parquet_column_convert.h b/be/src/format/parquet/parquet_column_convert.h index 5ec05d450d8b31..9fd02d660423ac 100644 --- a/be/src/format/parquet/parquet_column_convert.h +++ b/be/src/format/parquet/parquet_column_convert.h @@ -850,6 +850,38 @@ struct Int64ToTimestamp : public PhysicalToLogicalConverter { } }; +struct Int64ToTimestampNs : public PhysicalToLogicalConverter { + Status physical_convert(ColumnPtr& src_physical_col, ColumnPtr& src_logical_column) override { + const ColumnPtr src_col = remove_nullable(src_physical_col); + IColumn* dst_col = get_mutable_inner_column(src_logical_column); + + const auto& src_data = assert_cast(*src_col).get_data(); + auto& dst_data = assert_cast(*dst_col).get_data(); + const size_t start_idx = dst_data.size(); + dst_data.resize(start_idx + src_data.size()); + + for (size_t row = 0; row < src_data.size(); ++row) { + const TimeStampNsValue source(src_data[row]); + DateV2Value local; + if (_convert_params->is_fixed_offset) { + DORIS_CHECK(detail::try_convert_timestamp_with_fixed_offset( + local, source.epoch_seconds(), _convert_params->fixed_offset_seconds)); + } else { + DORIS_CHECK(detail::try_convert_timestamp_with_lookup(local, source.epoch_seconds(), + *_convert_params->ctz)); + } + local.set_microsecond(source.microsecond()); + if (!dst_data[start_idx + row].from_datetime(local, source.nanosecond_remainder())) { + return Status::DataQualityError( + "Parquet timestamp {} is outside the TIMESTAMP_NS range after timezone " + "conversion", + src_data[row]); + } + } + return Status::OK(); + } +}; + struct Int64ToTimestampTz : public PhysicalToLogicalConverter { Status physical_convert(ColumnPtr& src_physical_col, ColumnPtr& src_logical_column) override { ColumnPtr src_col = remove_nullable(src_physical_col); diff --git a/be/src/format/parquet/schema_desc.cpp b/be/src/format/parquet/schema_desc.cpp index 972ce6f969b74c..f125b2c7496e49 100644 --- a/be/src/format/parquet/schema_desc.cpp +++ b/be/src/format/parquet/schema_desc.cpp @@ -316,6 +316,10 @@ std::pair FieldDescriptor::convert_to_doris_type( return ans; } } + if (logicalType.TIMESTAMP.unit.__isset.NANOS) { + ans.first = DataTypeFactory::instance().create_data_type(TYPE_TIMESTAMP_NS, nullable); + return ans; + } ans.first = DataTypeFactory::instance().create_data_type( TYPE_DATETIMEV2, nullable, 0, logicalType.TIMESTAMP.unit.__isset.MILLIS ? 3 : 6); } else if (logicalType.__isset.JSON) { diff --git a/be/src/format/table/iceberg/arrow_schema_util.cpp b/be/src/format/table/iceberg/arrow_schema_util.cpp index 5515d5c43cf7eb..ca2c7e0b853f03 100644 --- a/be/src/format/table/iceberg/arrow_schema_util.cpp +++ b/be/src/format/table/iceberg/arrow_schema_util.cpp @@ -37,6 +37,8 @@ Status ArrowSchemaUtil::convert(const Schema* schema, const std::string& timezon return Status::OK(); } +// Keep the complete Iceberg-to-Arrow type mapping in one schema conversion function. +// NOLINTNEXTLINE(readability-function-size) Status ArrowSchemaUtil::convert_to(const iceberg::NestedField& field, std::shared_ptr* arrow_field, const std::string& timezone) { @@ -76,6 +78,13 @@ Status ArrowSchemaUtil::convert_to(const iceberg::NestedField& field, break; } + case iceberg::TypeID::TIMESTAMP_NANO: { + auto* t_type = static_cast(field.field_type()); + std::string real_tz = t_type->should_adjust_to_utc() ? timezone : ""; + arrow_type = std::make_shared(arrow::TimeUnit::NANO, real_tz); + break; + } + case iceberg::TypeID::STRING: arrow_type = arrow::utf8(); break; diff --git a/be/src/format/table/iceberg/types.cpp b/be/src/format/table/iceberg/types.cpp index 252f9035518c0b..5dfaf186b68db7 100644 --- a/be/src/format/table/iceberg/types.cpp +++ b/be/src/format/table/iceberg/types.cpp @@ -164,6 +164,10 @@ std::unique_ptr Types::from_primitive_string(const std::string& t return std::make_unique(true); } else if (lower_type_string == "timestamp") { return std::make_unique(false); + } else if (lower_type_string == "timestamptz_ns") { + return std::make_unique(true); + } else if (lower_type_string == "timestamp_ns") { + return std::make_unique(false); } else if (lower_type_string == "string") { return std::make_unique(); } else if (lower_type_string == "uuid") { diff --git a/be/src/format/table/iceberg/types.h b/be/src/format/table/iceberg/types.h index 1594003fccda68..c929e195f8ed18 100644 --- a/be/src/format/table/iceberg/types.h +++ b/be/src/format/table/iceberg/types.h @@ -48,7 +48,8 @@ enum TypeID { DECIMAL, STRUCT, LIST, - MAP + MAP, + TIMESTAMP_NANO }; class Type { @@ -335,6 +336,22 @@ class TimestampType : public PrimitiveType { bool _adjust_to_utc; }; +class TimestampNanoType : public PrimitiveType { +public: + explicit TimestampNanoType(bool adjust_to_utc) : _adjust_to_utc(adjust_to_utc) {} + + TypeID type_id() const override { return TypeID::TIMESTAMP_NANO; } + + bool should_adjust_to_utc() const { return _adjust_to_utc; } + + std::string to_string() const override { + return should_adjust_to_utc() ? "timestamptz_ns" : "timestamp_ns"; + } + +private: + bool _adjust_to_utc; +}; + class TimeType : public PrimitiveType { public: ~TimeType() override = default; diff --git a/be/src/format/table/iceberg_default_value.h b/be/src/format/table/iceberg_default_value.h index 5fe1834e3bcb23..457e8f0f4bdb8e 100644 --- a/be/src/format/table/iceberg_default_value.h +++ b/be/src/format/table/iceberg_default_value.h @@ -160,7 +160,7 @@ inline std::string json_scalar_text(const rapidjson::Value& value) { inline void normalize_timestamp_for_doris(doris::PrimitiveType primitive_type, std::string* value) { if (primitive_type != TYPE_DATETIME && primitive_type != TYPE_DATETIMEV2 && - primitive_type != TYPE_TIMESTAMPTZ) { + primitive_type != TYPE_TIMESTAMP_NS && primitive_type != TYPE_TIMESTAMPTZ) { return; } if (const size_t separator = value->find('T'); separator != std::string::npos) { diff --git a/be/src/format/table/paimon_predicate_converter.cpp b/be/src/format/table/paimon_predicate_converter.cpp index 6fa6d4907e7340..55461c163aef13 100644 --- a/be/src/format/table/paimon_predicate_converter.cpp +++ b/be/src/format/table/paimon_predicate_converter.cpp @@ -28,6 +28,7 @@ #include "core/field.h" #include "core/types.h" #include "core/value/decimalv2_value.h" +#include "core/value/timestamp_ns_value.h" #include "core/value/timestamptz_value.h" #include "core/value/vdatetime_value.h" #include "exprs/vcompound_pred.h" @@ -341,6 +342,9 @@ std::optional PaimonPredicateConverter::_re return FieldMeta {it->second, *field_type, slot_desc}; } +// Keep literal conversion centralized so every source/slot type combination has one strict +// compatibility check before predicate pushdown. +// NOLINTNEXTLINE(readability-function-size, readability-function-cognitive-complexity) std::optional PaimonPredicateConverter::_convert_literal( const VExprSPtr& expr, const SlotDescriptor& slot_desc, paimon::FieldType field_type) const { @@ -464,6 +468,19 @@ std::optional PaimonPredicateConverter::_convert_literal( int64_t millis = ts.first * 1000 + ts.second / 1000; return paimon::Literal(paimon::Timestamp::FromEpochMillis(millis)); } + case TYPE_TIMESTAMP_NS: { + if (literal_primitive != TYPE_TIMESTAMP_NS) { + return std::nullopt; + } + int64_t epoch_nanos = field.get().epoch_nanos(); + int64_t millis = epoch_nanos / 1'000'000; + auto nanos_of_millisecond = static_cast(epoch_nanos % 1'000'000); + if (nanos_of_millisecond < 0) { + --millis; + nanos_of_millisecond += 1'000'000; + } + return paimon::Literal(paimon::Timestamp::FromEpochMillis(millis, nanos_of_millisecond)); + } case TYPE_VARCHAR: case TYPE_STRING: { if (!_is_string_type(literal_primitive)) { @@ -637,6 +654,7 @@ std::optional PaimonPredicateConverter::_to_paimon_field_type return paimon::FieldType::DATE; case TYPE_DATETIME: case TYPE_DATETIMEV2: + case TYPE_TIMESTAMP_NS: return paimon::FieldType::TIMESTAMP; case TYPE_DECIMALV2: case TYPE_DECIMAL32: diff --git a/be/src/format/transformer/vorc_transformer.cpp b/be/src/format/transformer/vorc_transformer.cpp index ab8f3ffc978a15..39f19e1bf74ffd 100644 --- a/be/src/format/transformer/vorc_transformer.cpp +++ b/be/src/format/transformer/vorc_transformer.cpp @@ -234,6 +234,8 @@ void VOrcTransformer::set_compression_type(const TFileCompressType::type& compre } } +// Keep the complete Doris-to-ORC schema mapping in one recursive conversion function. +// NOLINTNEXTLINE(readability-function-size) std::unique_ptr VOrcTransformer::_build_orc_type( const DataTypePtr& data_type, const iceberg::NestedField* nested_field) { std::unique_ptr type; @@ -294,6 +296,10 @@ std::unique_ptr VOrcTransformer::_build_orc_type( type = orc::createPrimitiveType(orc::TIMESTAMP); break; } + case TYPE_TIMESTAMP_NS: { + type = orc::createPrimitiveType(orc::TIMESTAMP); + break; + } case TYPE_DECIMAL32: { type = orc::createDecimalType(data_type->get_precision(), data_type->get_scale()); break; diff --git a/be/src/format_v2/column_data.h b/be/src/format_v2/column_data.h index 41593fa157dacb..42db05e2e820b8 100644 --- a/be/src/format_v2/column_data.h +++ b/be/src/format_v2/column_data.h @@ -277,6 +277,9 @@ struct ColumnDefinition { // Logical timestamp semantic supplied by a table format when the physical encoding cannot // carry it (for example, Paimon TIMESTAMP versus TIMESTAMP_LTZ stored as INT96). std::optional timestamp_is_adjusted_to_utc = std::nullopt; + // High-precision timestamp semantic supplied by a table format when the file schema cannot + // distinguish nanosecond timestamps from microsecond timestamps. + bool timestamp_is_nanosecond = false; // Partition columns are constants from split metadata and should not be matched against file // schema unless table-format logic explicitly asks for it. bool is_partition_key = false; @@ -359,6 +362,7 @@ struct LocalColumnIndex { bool project_all_children = true; std::vector children {}; std::optional timestamp_is_adjusted_to_utc = std::nullopt; + bool timestamp_is_nanosecond = false; static LocalColumnIndex top_level(LocalColumnId column_id) { return {.index = column_id.value()}; @@ -413,6 +417,7 @@ inline Status merge_local_column_index(LocalColumnIndex* target, const LocalColu return Status::InvalidArgument("Conflicting timestamp semantics for file-local column {}", target->index); } + target->timestamp_is_nanosecond |= source.timestamp_is_nanosecond; if (target->project_all_children) { return Status::OK(); } diff --git a/be/src/format_v2/column_mapper.cpp b/be/src/format_v2/column_mapper.cpp index 9f433cc853f61a..d6377af88ee15e 100644 --- a/be/src/format_v2/column_mapper.cpp +++ b/be/src/format_v2/column_mapper.cpp @@ -388,6 +388,7 @@ std::string ColumnDefinition::debug_string() const { << ", name_mapping=" << join_debug_strings(name_mapping, [](const std::string& name) { return name; }) << ", has_name_mapping=" << has_name_mapping << ", local_id=" << local_id + << ", timestamp_is_nanosecond=" << timestamp_is_nanosecond << ", timestamp_is_adjusted_to_utc=" << (timestamp_is_adjusted_to_utc.has_value() ? (*timestamp_is_adjusted_to_utc ? "true" : "false") @@ -412,6 +413,7 @@ std::string ColumnDefinition::debug_string() const { std::string LocalColumnIndex::debug_string() const { std::ostringstream out; out << "LocalColumnIndex{index=" << index << ", project_all_children=" << project_all_children + << ", timestamp_is_nanosecond=" << timestamp_is_nanosecond << ", timestamp_is_adjusted_to_utc=" << (timestamp_is_adjusted_to_utc.has_value() ? (*timestamp_is_adjusted_to_utc ? "true" : "false") @@ -438,7 +440,9 @@ std::string ColumnMapping::debug_string() const { } else { out << "null"; } - out << ", file_column_name=" << file_column_name << ", timestamp_is_adjusted_to_utc=" + out << ", file_column_name=" << file_column_name + << ", timestamp_is_nanosecond=" << timestamp_is_nanosecond + << ", timestamp_is_adjusted_to_utc=" << (timestamp_is_adjusted_to_utc.has_value() ? (*timestamp_is_adjusted_to_utc ? "true" : "false") : "unset") @@ -1712,6 +1716,7 @@ static Status build_complex_projection(const ColumnMapping& mapping, LocalColumn DORIS_CHECK(mapping.file_local_id.has_value()); *projection = LocalColumnIndex::local(*mapping.file_local_id); projection->timestamp_is_adjusted_to_utc = mapping.timestamp_is_adjusted_to_utc; + projection->timestamp_is_nanosecond = mapping.timestamp_is_nanosecond; projection->project_all_children = mapping.child_mappings.empty(); projection->children.clear(); const auto present_children = present_child_mappings_in_file_order(mapping.child_mappings); @@ -1735,13 +1740,14 @@ static Status build_complex_projection(const ColumnMapping& mapping, LocalColumn } static bool has_timestamp_semantics(const ColumnMapping& mapping) { - return mapping.timestamp_is_adjusted_to_utc.has_value() || + return mapping.timestamp_is_adjusted_to_utc.has_value() || mapping.timestamp_is_nanosecond || std::ranges::any_of(mapping.child_mappings, has_timestamp_semantics); } static void attach_timestamp_semantics(const ColumnMapping& mapping, LocalColumnIndex* projection) { DORIS_CHECK(projection != nullptr); projection->timestamp_is_adjusted_to_utc = mapping.timestamp_is_adjusted_to_utc; + projection->timestamp_is_nanosecond = mapping.timestamp_is_nanosecond; for (const auto& child_mapping : mapping.child_mappings) { // A full projection represents ordinary children implicitly; materialize only paths that // carry an override so existing readers still observe an empty children list. @@ -1817,6 +1823,7 @@ static Status add_scan_column(FileScanRequest* file_request, ColumnMapping* mapp const auto file_column_id = LocalColumnId(mapping->file_local_id.value()); LocalColumnIndex projection = LocalColumnIndex::top_level(file_column_id); projection.timestamp_is_adjusted_to_utc = mapping->timestamp_is_adjusted_to_utc; + projection.timestamp_is_nanosecond = mapping->timestamp_is_nanosecond; // Columnar readers can turn a complex mapping into a nested file projection, but // row-oriented readers must scan the full top-level complex field because all children are // encoded in the same text cell. @@ -2459,6 +2466,7 @@ Status TableColumnMapper::_create_direct_mapping(const ColumnDefinition& table_c mapping->original_file_children = file_field.children; mapping->projected_file_children = file_field.children; mapping->timestamp_is_adjusted_to_utc = file_field.timestamp_is_adjusted_to_utc; + mapping->timestamp_is_nanosecond = file_field.timestamp_is_nanosecond; mapping->file_type = file_field.type; mapping->is_trivial = mapping_can_use_file_column_directly(*mapping); mapping->filter_conversion = direct_filter_conversion(*mapping); diff --git a/be/src/format_v2/column_mapper.h b/be/src/format_v2/column_mapper.h index eb652833be81a9..7fecec42d986a4 100644 --- a/be/src/format_v2/column_mapper.h +++ b/be/src/format_v2/column_mapper.h @@ -129,6 +129,7 @@ struct ColumnMapping { // file-local block layout when projection, predicate-only children, and schema evolution mix. std::vector projected_file_children; std::optional timestamp_is_adjusted_to_utc = std::nullopt; + bool timestamp_is_nanosecond = false; // Split/file-local constant entry when this mapping is produced from partition/default/virtual // expression instead of physical file data. std::optional constant_index; diff --git a/be/src/format_v2/parquet/native_schema_desc.cpp b/be/src/format_v2/parquet/native_schema_desc.cpp index 9eba6d8feaa55a..abb98cb8606db3 100644 --- a/be/src/format_v2/parquet/native_schema_desc.cpp +++ b/be/src/format_v2/parquet/native_schema_desc.cpp @@ -434,6 +434,10 @@ std::pair NativeFieldDescriptor::convert_to_doris_type( return ans; } } + if (logicalType.TIMESTAMP.unit.__isset.NANOS) { + ans.first = DataTypeFactory::instance().create_data_type(TYPE_TIMESTAMP_NS, nullable); + return ans; + } ans.first = DataTypeFactory::instance().create_data_type( TYPE_DATETIMEV2, nullable, 0, logicalType.TIMESTAMP.unit.__isset.MILLIS ? 3 : 6); } else if (logicalType.__isset.UUID) { diff --git a/be/src/format_v2/parquet/parquet_reader.cpp b/be/src/format_v2/parquet/parquet_reader.cpp index 0e934d0c9bbe45..43884f86c7f5b1 100644 --- a/be/src/format_v2/parquet/parquet_reader.cpp +++ b/be/src/format_v2/parquet/parquet_reader.cpp @@ -241,8 +241,12 @@ DataTypePtr apply_projection_timestamp_semantics(ParquetColumnSchema* column_sch const bool physical_timestamp = descriptor.physical_type == tparquet::Type::INT96 || descriptor.is_timestamp; if (physical_timestamp && projection.timestamp_is_adjusted_to_utc.has_value()) { - const auto target = - *projection.timestamp_is_adjusted_to_utc ? TYPE_TIMESTAMPTZ : TYPE_DATETIMEV2; + PrimitiveType target = TYPE_DATETIMEV2; + if (*projection.timestamp_is_adjusted_to_utc) { + target = TYPE_TIMESTAMPTZ; + } else if (projection.timestamp_is_nanosecond) { + target = TYPE_TIMESTAMP_NS; + } column_schema->type = DataTypeFactory::instance().create_data_type( target, column_schema->type != nullptr && column_schema->type->is_nullable(), 0, timestamp_tz_scale(descriptor)); diff --git a/be/src/format_v2/parquet/parquet_scan.cpp b/be/src/format_v2/parquet/parquet_scan.cpp index a9154021999a4f..2eb68a792fba16 100644 --- a/be/src/format_v2/parquet/parquet_scan.cpp +++ b/be/src/format_v2/parquet/parquet_scan.cpp @@ -1536,6 +1536,7 @@ bool get_typed_dictionary_raw_values(PrimitiveType primitive_type, const IColumn GET_TYPED_DICTIONARY_VALUES(TYPE_DATETIME); GET_TYPED_DICTIONARY_VALUES(TYPE_DATEV2); GET_TYPED_DICTIONARY_VALUES(TYPE_DATETIMEV2); + GET_TYPED_DICTIONARY_VALUES(TYPE_TIMESTAMP_NS); GET_TYPED_DICTIONARY_VALUES(TYPE_TIMESTAMPTZ); GET_TYPED_DICTIONARY_VALUES(TYPE_DECIMAL32); GET_TYPED_DICTIONARY_VALUES(TYPE_DECIMAL64); diff --git a/be/src/format_v2/table/paimon_reader.cpp b/be/src/format_v2/table/paimon_reader.cpp index 7ec276ebe105a1..a78c28ea9ee1b3 100644 --- a/be/src/format_v2/table/paimon_reader.cpp +++ b/be/src/format_v2/table/paimon_reader.cpp @@ -48,8 +48,12 @@ DataTypePtr apply_paimon_timestamp_semantics(format::ColumnDefinition* column) { const auto primitive = remove_nullable(column->type)->get_primitive_type(); if (column->timestamp_is_adjusted_to_utc.has_value() && (primitive == TYPE_DATETIMEV2 || primitive == TYPE_TIMESTAMPTZ)) { - const auto target = - *column->timestamp_is_adjusted_to_utc ? TYPE_TIMESTAMPTZ : TYPE_DATETIMEV2; + PrimitiveType target = TYPE_DATETIMEV2; + if (*column->timestamp_is_adjusted_to_utc) { + target = TYPE_TIMESTAMPTZ; + } else if (column->timestamp_is_nanosecond) { + target = TYPE_TIMESTAMP_NS; + } column->type = DataTypeFactory::instance().create_data_type( target, column->type->is_nullable(), 0, column->type->get_scale()); return column->type; diff --git a/be/src/format_v2/table/schema_history_util.cpp b/be/src/format_v2/table/schema_history_util.cpp index 96a466fa772837..dc7ed307861990 100644 --- a/be/src/format_v2/table/schema_history_util.cpp +++ b/be/src/format_v2/table/schema_history_util.cpp @@ -83,6 +83,8 @@ void annotate_column_from_field(ColumnDefinition* column, const schema::external field.__isset.timestamp_is_adjusted_to_utc ? std::make_optional(field.timestamp_is_adjusted_to_utc) : std::nullopt; + column->timestamp_is_nanosecond = + field.__isset.type && field.type.type == TPrimitiveType::TIMESTAMP_NS; if (!field.__isset.nestedField) { return; } diff --git a/be/src/information_schema/schema_columns_scanner.cpp b/be/src/information_schema/schema_columns_scanner.cpp index 55eccbf3b53a48..23394f5ce38318 100644 --- a/be/src/information_schema/schema_columns_scanner.cpp +++ b/be/src/information_schema/schema_columns_scanner.cpp @@ -134,6 +134,8 @@ std::string SchemaColumnsScanner::_to_mysql_data_type_string(TColumnDesc& desc) case TPrimitiveType::DATETIME: case TPrimitiveType::DATETIMEV2: return "datetime"; + case TPrimitiveType::TIMESTAMP_NS: + return "timestamp_ns"; case TPrimitiveType::TIMESTAMPTZ: return "timestamp"; case TPrimitiveType::DECIMAL32: diff --git a/be/src/runtime/fold_constant_executor.cpp b/be/src/runtime/fold_constant_executor.cpp index 97efd2d72deb5b..7aab2c458c6474 100644 --- a/be/src/runtime/fold_constant_executor.cpp +++ b/be/src/runtime/fold_constant_executor.cpp @@ -265,6 +265,11 @@ Status FoldConstantExecutor::_get_result(void* src, size_t size, const DataTypeP result = CastToString::from_datetimev2(value, type->get_scale()); break; } + case TYPE_TIMESTAMP_NS: { + const auto value = TimeStampNsValue(*reinterpret_cast(src)); + result = value.to_string(); + break; + } case TYPE_TIMESTAMPTZ: { auto value = binary_cast(*(int64_t*)src); result = CastToString::from_timestamptz(value, type->get_scale(), options.timezone); @@ -298,4 +303,4 @@ Status FoldConstantExecutor::_get_result(void* src, size_t size, const DataTypeP return Status::OK(); } -} // namespace doris \ No newline at end of file +} // namespace doris diff --git a/be/src/runtime/runtime_predicate.cpp b/be/src/runtime/runtime_predicate.cpp index 61d518e2beeb2a..b20d7b9a857c48 100644 --- a/be/src/runtime/runtime_predicate.cpp +++ b/be/src/runtime/runtime_predicate.cpp @@ -82,7 +82,8 @@ Status RuntimePredicate::init_target( bool RuntimePredicate::_init(PrimitiveType type) { return is_int_or_bool(type) || is_decimal(type) || is_string_type(type) || is_date_type(type) || - is_time_type(type) || is_timestamptz_type(type) || is_ip(type) || is_varbinary(type); + is_timestamp_ns_type(type) || is_time_type(type) || is_timestamptz_type(type) || + is_ip(type) || is_varbinary(type); } Status RuntimePredicate::update(const Field& value) { diff --git a/be/src/storage/delete/delete_handler.cpp b/be/src/storage/delete/delete_handler.cpp index 1781c7734de7d0..132a0cb12eb3e0 100644 --- a/be/src/storage/delete/delete_handler.cpp +++ b/be/src/storage/delete/delete_handler.cpp @@ -28,6 +28,7 @@ #include "common/logging.h" #include "common/status.h" #include "core/data_type_serde/data_type_serde.h" +#include "core/data_type_serde/data_type_timestamp_ns_serde.h" #include "storage/olap_common.h" #include "storage/predicate/block_column_predicate.h" #include "storage/predicate/null_predicate.h" @@ -88,6 +89,7 @@ Status convert(const DataTypePtr& data_type, const std::list& str, FROM_FE_STRING_CASE(TYPE_DATETIME); FROM_FE_STRING_CASE(TYPE_DATEV2); FROM_FE_STRING_CASE(TYPE_DATETIMEV2); + FROM_FE_STRING_CASE(TYPE_TIMESTAMP_NS); FROM_FE_STRING_CASE(TYPE_TIMESTAMPTZ); FROM_FE_STRING_CASE(TYPE_BOOLEAN); FROM_FE_STRING_CASE(TYPE_IPV4); @@ -359,6 +361,10 @@ bool DeleteHandler::is_condition_value_valid(const TabletColumn& column, case FieldType::OLAP_FIELD_TYPE_DATETIMEV2: case FieldType::OLAP_FIELD_TYPE_TIMESTAMPTZ: return valid_datetime(value_str, column.frac()); + case FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS: { + int64_t epoch_nanos = 0; + return parse_timestamp_ns(StringRef(value_str), &epoch_nanos).ok(); + } case FieldType::OLAP_FIELD_TYPE_BOOL: return valid_bool(value_str); case FieldType::OLAP_FIELD_TYPE_IPV4: diff --git a/be/src/storage/index/bloom_filter/bloom_filter_index_writer.cpp b/be/src/storage/index/bloom_filter/bloom_filter_index_writer.cpp index 785e889a831eee..8d6a7aec6015fb 100644 --- a/be/src/storage/index/bloom_filter/bloom_filter_index_writer.cpp +++ b/be/src/storage/index/bloom_filter/bloom_filter_index_writer.cpp @@ -330,6 +330,7 @@ Status BloomFilterIndexWriter::create(const BloomFilterOptions& bf_options, Fiel M(FieldType::OLAP_FIELD_TYPE_DECIMAL) M(FieldType::OLAP_FIELD_TYPE_DATEV2) M(FieldType::OLAP_FIELD_TYPE_DATETIMEV2) + M(FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS) M(FieldType::OLAP_FIELD_TYPE_TIMESTAMPTZ) M(FieldType::OLAP_FIELD_TYPE_DECIMAL32) M(FieldType::OLAP_FIELD_TYPE_DECIMAL64) diff --git a/be/src/storage/index/index_writer.cpp b/be/src/storage/index/index_writer.cpp index 2325d280471337..785c37be49e293 100644 --- a/be/src/storage/index/index_writer.cpp +++ b/be/src/storage/index/index_writer.cpp @@ -102,6 +102,7 @@ Status IndexColumnWriter::create(const TabletColumn* column, M(FieldType::OLAP_FIELD_TYPE_DECIMAL) M(FieldType::OLAP_FIELD_TYPE_DATEV2) M(FieldType::OLAP_FIELD_TYPE_DATETIMEV2) + M(FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS) M(FieldType::OLAP_FIELD_TYPE_TIMESTAMPTZ) M(FieldType::OLAP_FIELD_TYPE_DECIMAL32) M(FieldType::OLAP_FIELD_TYPE_DECIMAL64) diff --git a/be/src/storage/index/inverted/inverted_index_writer.cpp b/be/src/storage/index/inverted/inverted_index_writer.cpp index 0f82b5225e666e..519568c28eb0bf 100644 --- a/be/src/storage/index/inverted/inverted_index_writer.cpp +++ b/be/src/storage/index/inverted/inverted_index_writer.cpp @@ -672,6 +672,7 @@ template class InvertedIndexColumnWriter; template class InvertedIndexColumnWriter; template class InvertedIndexColumnWriter; template class InvertedIndexColumnWriter; +template class InvertedIndexColumnWriter; template class InvertedIndexColumnWriter; template class InvertedIndexColumnWriter; template class InvertedIndexColumnWriter; @@ -683,4 +684,4 @@ template class InvertedIndexColumnWriter; template class InvertedIndexColumnWriter; template class InvertedIndexColumnWriter; -} // namespace doris::segment_v2 \ No newline at end of file +} // namespace doris::segment_v2 diff --git a/be/src/storage/index/zone_map/zone_map_index.cpp b/be/src/storage/index/zone_map/zone_map_index.cpp index 23e2e5a4a0feec..cd687b4a623735 100644 --- a/be/src/storage/index/zone_map/zone_map_index.cpp +++ b/be/src/storage/index/zone_map/zone_map_index.cpp @@ -358,6 +358,7 @@ ZoneMapIndexReader::~ZoneMapIndexReader() = default; M(TYPE_DATETIME) \ M(TYPE_DATEV2) \ M(TYPE_DATETIMEV2) \ + M(TYPE_TIMESTAMP_NS) \ M(TYPE_TIMESTAMPTZ) \ M(TYPE_IPV4) \ M(TYPE_IPV6) \ diff --git a/be/src/storage/iterator/olap_data_convertor.cpp b/be/src/storage/iterator/olap_data_convertor.cpp index 129253fbbbb4ff..2a774463e7e3f8 100644 --- a/be/src/storage/iterator/olap_data_convertor.cpp +++ b/be/src/storage/iterator/olap_data_convertor.cpp @@ -168,6 +168,9 @@ OlapBlockDataConvertor::create_olap_column_data_convertor(const TabletColumn& co case FieldType::OLAP_FIELD_TYPE_DATETIMEV2: { return std::make_unique(); } + case FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS: { + return std::make_unique>(); + } case FieldType::OLAP_FIELD_TYPE_TIMESTAMPTZ: { return std::make_unique>(); } diff --git a/be/src/storage/key_coder.cpp b/be/src/storage/key_coder.cpp index d7a4d7b1457724..e683b299e9bb1d 100644 --- a/be/src/storage/key_coder.cpp +++ b/be/src/storage/key_coder.cpp @@ -77,6 +77,7 @@ class KeyCoderResolver { add_mapping(); add_mapping(); add_mapping(); + add_mapping(); add_mapping(); add_mapping(); add_mapping(); diff --git a/be/src/storage/key_coder.h b/be/src/storage/key_coder.h index 0c4bcf08d171e5..803e5c9c7326d2 100644 --- a/be/src/storage/key_coder.h +++ b/be/src/storage/key_coder.h @@ -469,6 +469,7 @@ class KeyCoderTraits M(OLAP_FIELD_TYPE_DATETIME, TYPE_DATETIME) \ M(OLAP_FIELD_TYPE_DATEV2, TYPE_DATEV2) \ M(OLAP_FIELD_TYPE_DATETIMEV2, TYPE_DATETIMEV2) \ + M(OLAP_FIELD_TYPE_TIMESTAMP_NS, TYPE_TIMESTAMP_NS) \ M(OLAP_FIELD_TYPE_TIMESTAMPTZ, TYPE_TIMESTAMPTZ) \ M(OLAP_FIELD_TYPE_IPV4, TYPE_IPV4) \ M(OLAP_FIELD_TYPE_IPV6, TYPE_IPV6) diff --git a/be/src/storage/olap_common.h b/be/src/storage/olap_common.h index 51f23f93cd1bd1..974ae8dd2fd025 100644 --- a/be/src/storage/olap_common.h +++ b/be/src/storage/olap_common.h @@ -175,6 +175,7 @@ enum class FieldType { OLAP_FIELD_TYPE_IPV4 = 38, OLAP_FIELD_TYPE_IPV6 = 39, OLAP_FIELD_TYPE_TIMESTAMPTZ = 40, + OLAP_FIELD_TYPE_TIMESTAMP_NS = 41, }; // Define all aggregation methods supported by TabletColumn @@ -231,6 +232,7 @@ constexpr bool field_is_numeric_type(const FieldType& field_type) { field_type == FieldType::OLAP_FIELD_TYPE_DATEV2 || field_type == FieldType::OLAP_FIELD_TYPE_DATETIME || field_type == FieldType::OLAP_FIELD_TYPE_DATETIMEV2 || + field_type == FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS || field_type == FieldType::OLAP_FIELD_TYPE_TIMESTAMPTZ || field_type == FieldType::OLAP_FIELD_TYPE_LARGEINT || field_type == FieldType::OLAP_FIELD_TYPE_DECIMAL || diff --git a/be/src/storage/olap_scan_common.h b/be/src/storage/olap_scan_common.h index f7162f3b1f12b4..c14596f86ad4f8 100644 --- a/be/src/storage/olap_scan_common.h +++ b/be/src/storage/olap_scan_common.h @@ -233,6 +233,7 @@ class ColumnValueRange { primitive_type == PrimitiveType::TYPE_BOOLEAN || primitive_type == PrimitiveType::TYPE_DATETIME || primitive_type == PrimitiveType::TYPE_DATETIMEV2 || + primitive_type == PrimitiveType::TYPE_TIMESTAMP_NS || primitive_type == PrimitiveType::TYPE_TIMESTAMPTZ || primitive_type == PrimitiveType::TYPE_DECIMAL256; }; @@ -337,10 +338,10 @@ using ColumnValueRangeType = std::variant< ColumnValueRange, ColumnValueRange, ColumnValueRange, ColumnValueRange, ColumnValueRange, ColumnValueRange, ColumnValueRange, ColumnValueRange, - ColumnValueRange, ColumnValueRange, - ColumnValueRange, ColumnValueRange, - ColumnValueRange, ColumnValueRange, - ColumnValueRange>; + ColumnValueRange, ColumnValueRange, + ColumnValueRange, ColumnValueRange, + ColumnValueRange, ColumnValueRange, + ColumnValueRange, ColumnValueRange>; template const typename ColumnValueRange::CppType diff --git a/be/src/storage/partial_update_info.cpp b/be/src/storage/partial_update_info.cpp index 1bea6e05cb75f5..b10699b169b625 100644 --- a/be/src/storage/partial_update_info.cpp +++ b/be/src/storage/partial_update_info.cpp @@ -28,6 +28,8 @@ #include "core/block/block.h" #include "core/data_type/data_type_number.h" // IWYU pragma: keep #include "core/value/bitmap_value.h" +#include "core/value/timestamp_ns_value.h" +#include "exec/common/int_exp.h" #include "storage/iterator/olap_data_convertor.h" #include "storage/key/row_key_encoder.h" #include "storage/olap_common.h" @@ -51,6 +53,36 @@ ColumnBitmap* get_mutable_skip_bitmap_column(Block* block, size_t skip_bitmap_co return skip_bitmap_column_ptr; } +std::string materialize_current_timestamp_default(FieldType type, + const std::string& default_expression, + int64_t timestamp_ms, int32_t nano_seconds, + const std::string& timezone) { + const auto precision_pos = to_lower(default_expression).find('('); + const int precision = precision_pos == std::string::npos + ? 0 + : std::stoi(default_expression.substr(precision_pos + 1)); + + DateV2Value datetime; + datetime.from_unixtime(timestamp_ms / 1000, nano_seconds, timezone, precision); + if (type == FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS) { + uint16_t nanosecond_remainder = 0; + if (precision > 6) { + const int64_t factor = static_cast(int_exp10(9 - precision)); + const int64_t truncated_nanos = nano_seconds / factor * factor; + nanosecond_remainder = static_cast(truncated_nanos % 1000); + } + TimeStampNsValue timestamp_ns; + DORIS_CHECK(timestamp_ns.from_datetime(datetime, nanosecond_remainder)); + return timestamp_ns.to_string(); + } + + std::string value = datetime.to_string(); + if (type == FieldType::OLAP_FIELD_TYPE_TIMESTAMPTZ) { + value += timezone; + } + return value; +} + } // namespace Status PartialUpdateInfo::init(int64_t tablet_id, int64_t txn_id, const TabletSchema& tablet_schema, @@ -273,26 +305,13 @@ void PartialUpdateInfo::_generate_default_values_for_missing_cids( if (column.has_default_value()) { std::string default_value; if (UNLIKELY((column.type() == FieldType::OLAP_FIELD_TYPE_DATETIMEV2 || + column.type() == FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS || column.type() == FieldType::OLAP_FIELD_TYPE_TIMESTAMPTZ) && to_lower(column.default_value()).find(to_lower("CURRENT_TIMESTAMP")) != std::string::npos)) { - auto pos = to_lower(column.default_value()).find('('); - if (pos == std::string::npos) { - DateV2Value dtv; - dtv.from_unixtime(timestamp_ms / 1000, timezone); - default_value = dtv.to_string(); - if (column.type() == FieldType::OLAP_FIELD_TYPE_TIMESTAMPTZ) { - default_value += timezone; - } - } else { - int precision = std::stoi(column.default_value().substr(pos + 1)); - DateV2Value dtv; - dtv.from_unixtime(timestamp_ms / 1000, nano_seconds, timezone, precision); - default_value = dtv.to_string(); - if (column.type() == FieldType::OLAP_FIELD_TYPE_TIMESTAMPTZ) { - default_value += timezone; - } - } + default_value = + materialize_current_timestamp_default(column.type(), column.default_value(), + timestamp_ms, nano_seconds, timezone); } else if (UNLIKELY(column.type() == FieldType::OLAP_FIELD_TYPE_DATEV2 && to_lower(column.default_value()).find(to_lower("CURRENT_DATE")) != std::string::npos)) { diff --git a/be/src/storage/predicate/predicate_creator.cpp b/be/src/storage/predicate/predicate_creator.cpp index 485ca89eea6f49..bcfdf93ef15386 100644 --- a/be/src/storage/predicate/predicate_creator.cpp +++ b/be/src/storage/predicate/predicate_creator.cpp @@ -94,6 +94,10 @@ std::shared_ptr create_bloom_filter_predicate( return BloomFilterColumnPredicate::create_shared(cid, col_name, filter_olap); } + case TYPE_TIMESTAMP_NS: { + return BloomFilterColumnPredicate::create_shared(cid, col_name, + filter_olap); + } case TYPE_TIMESTAMPTZ: { return BloomFilterColumnPredicate::create_shared(cid, col_name, filter_olap); diff --git a/be/src/storage/predicate/predicate_creator_comparison.cpp b/be/src/storage/predicate/predicate_creator_comparison.cpp index b10a175b016592..d444a35a0845b8 100644 --- a/be/src/storage/predicate/predicate_creator_comparison.cpp +++ b/be/src/storage/predicate/predicate_creator_comparison.cpp @@ -102,6 +102,10 @@ std::shared_ptr create_comparison_predicate(const uint32_t cid, return ComparisonPredicateBase::create_shared(cid, col_name, value, opposite); } + case TYPE_TIMESTAMP_NS: { + return ComparisonPredicateBase::create_shared(cid, col_name, value, + opposite); + } case TYPE_TIMESTAMPTZ: { return ComparisonPredicateBase::create_shared(cid, col_name, value, opposite); diff --git a/be/src/storage/predicate/predicate_creator_in_list_in.cpp b/be/src/storage/predicate/predicate_creator_in_list_in.cpp index f1ad365b4f523e..9162d02506f735 100644 --- a/be/src/storage/predicate/predicate_creator_in_list_in.cpp +++ b/be/src/storage/predicate/predicate_creator_in_list_in.cpp @@ -139,6 +139,10 @@ std::shared_ptr create_in_list_predicate( cid, col_name, set, is_opposite); } + case TYPE_TIMESTAMP_NS: { + return create_in_list_predicate_impl( + cid, col_name, set, is_opposite); + } case TYPE_TIMESTAMPTZ: { return create_in_list_predicate_impl( cid, col_name, set, is_opposite); diff --git a/be/src/storage/predicate/predicate_creator_in_list_not_in.cpp b/be/src/storage/predicate/predicate_creator_in_list_not_in.cpp index e4cb4731a57095..d90d8538dffca9 100644 --- a/be/src/storage/predicate/predicate_creator_in_list_not_in.cpp +++ b/be/src/storage/predicate/predicate_creator_in_list_not_in.cpp @@ -139,6 +139,10 @@ std::shared_ptr create_in_list_predicate( cid, col_name, set, is_opposite); } + case TYPE_TIMESTAMP_NS: { + return create_in_list_predicate_impl( + cid, col_name, set, is_opposite); + } case TYPE_TIMESTAMPTZ: { return create_in_list_predicate_impl( cid, col_name, set, is_opposite); diff --git a/be/src/storage/segment/encoding_info.cpp b/be/src/storage/segment/encoding_info.cpp index d2b9d99f114e85..5c15d34de3e062 100644 --- a/be/src/storage/segment/encoding_info.cpp +++ b/be/src/storage/segment/encoding_info.cpp @@ -306,6 +306,9 @@ EncodingInfoResolver::EncodingInfoResolver() { _register_supported_encoding(); _register_supported_encoding(); _register_supported_encoding(); + _register_supported_encoding(); + _register_supported_encoding(); + _register_supported_encoding(); _register_supported_encoding(); _register_supported_encoding(); _register_supported_encoding(); @@ -364,6 +367,7 @@ EncodingInfoResolver::EncodingInfoResolver() { _set_v2_default(); _set_v2_default(); _set_v2_default(); + _set_v2_default(); _set_v2_default(); _set_v2_default(); _set_v2_default(); @@ -397,6 +401,7 @@ EncodingInfoResolver::EncodingInfoResolver() { _set_v3_default(); _set_v3_default(); _set_v3_default(); + _set_v3_default(); _set_v3_default(); _set_v3_default(); _set_v3_default(); diff --git a/be/src/storage/segment/variant/v2/variant_path_builder.cpp b/be/src/storage/segment/variant/v2/variant_path_builder.cpp index c7542669fe40fc..1d6b7775004075 100644 --- a/be/src/storage/segment/variant/v2/variant_path_builder.cpp +++ b/be/src/storage/segment/variant/v2/variant_path_builder.cpp @@ -44,10 +44,12 @@ #include "core/data_type/data_type_nullable.h" #include "core/data_type/data_type_number.h" #include "core/data_type/data_type_string.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/data_type/data_type_timestamptz.h" #include "core/data_type/get_least_supertype.h" #include "core/data_type/primitive_type.h" #include "core/typeid_cast.h" +#include "core/value/timestamp_ns_value.h" #include "core/value/timestamptz_value.h" #include "core/value/vdatetime_value.h" #include "exec/common/variant_util.h" @@ -68,6 +70,7 @@ enum class ValueKind : uint8_t { DECIMAL, DATE, TIMESTAMP_NTZ, + TIMESTAMP_NTZ_NANOS, TIMESTAMP_TZ, STRING, JSONB_REF, @@ -165,10 +168,11 @@ ValueKind value_kind(VariantRef value) { return ValueKind::TIMESTAMP_TZ; case VariantPrimitiveId::TIMESTAMP_NTZ_MICROS: return ValueKind::TIMESTAMP_NTZ; + case VariantPrimitiveId::TIMESTAMP_NTZ_NANOS: + return ValueKind::TIMESTAMP_NTZ_NANOS; case VariantPrimitiveId::BINARY: case VariantPrimitiveId::TIME_NTZ_MICROS: case VariantPrimitiveId::TIMESTAMP_NANOS: - case VariantPrimitiveId::TIMESTAMP_NTZ_NANOS: case VariantPrimitiveId::UUID: return ValueKind::JSONB_REF; } @@ -257,6 +261,10 @@ DataTypePtr infer_type(VariantRef value, const DataTypePtr& reusable_type = null static const DataTypePtr type = std::make_shared(6); return type; } + case ValueKind::TIMESTAMP_NTZ_NANOS: { + static const DataTypePtr type = std::make_shared(); + return type; + } case ValueKind::TIMESTAMP_TZ: { if (!timestamp_fits_doris_range(value.get_timestamp_micros())) { return jsonb_type(); @@ -348,6 +356,10 @@ DataTypePtr path_least_common_type(const DataTypePtr& left, const DataTypePtr& r } const PrimitiveType left_primitive = left->get_primitive_type(); const PrimitiveType right_primitive = right->get_primitive_type(); + if ((left_primitive == TYPE_TIMESTAMP_NS && right_primitive == TYPE_DATETIMEV2) || + (left_primitive == TYPE_DATETIMEV2 && right_primitive == TYPE_TIMESTAMP_NS)) { + return left_primitive == TYPE_TIMESTAMP_NS ? left : right; + } const bool left_decimal = left_primitive == TYPE_DECIMAL128I; const bool right_decimal = right_primitive == TYPE_DECIMAL128I; // get_least_supertype_jsonb() treats equal primitive ids as the same type. Decimal128(38, 2) @@ -448,6 +460,15 @@ bool value_is_representable(VariantRef value, const DataTypePtr& target_type) { case TYPE_DATETIMEV2: return kind == ValueKind::TIMESTAMP_NTZ && timestamp_fits_doris_range(value.get_timestamp_ntz_micros()); + case TYPE_TIMESTAMP_NS: { + if (kind == ValueKind::TIMESTAMP_NTZ_NANOS) { + return true; + } + int64_t nanos = 0; + return kind == ValueKind::TIMESTAMP_NTZ && + !__builtin_mul_overflow(value.get_timestamp_ntz_micros(), + TimeStampNsValue::NANOS_PER_MICROSECOND, &nanos); + } case TYPE_TIMESTAMPTZ: return kind == ValueKind::TIMESTAMP_TZ && timestamp_fits_doris_range(value.get_timestamp_micros()); @@ -519,6 +540,7 @@ void write_path_jsonb(VariantRef value, JsonbWriter* writer) { case ValueKind::BOOL: case ValueKind::DATE: case ValueKind::TIMESTAMP_NTZ: + case ValueKind::TIMESTAMP_NTZ_NANOS: case ValueKind::TIMESTAMP_TZ: case ValueKind::STRING: case ValueKind::JSONB_REF: { @@ -539,6 +561,7 @@ void append_jsonb(VariantRef value, ColumnString* column) { case ValueKind::BOOL: case ValueKind::DATE: case ValueKind::TIMESTAMP_NTZ: + case ValueKind::TIMESTAMP_NTZ_NANOS: case ValueKind::TIMESTAMP_TZ: case ValueKind::STRING: case ValueKind::JSONB_REF: @@ -655,10 +678,25 @@ void append_date(VariantRef value, IColumn* target) { void append_timestamp(VariantRef value, PrimitiveType target_type, IColumn* target) { const ValueKind kind = value_kind(value); - if (kind != ValueKind::TIMESTAMP_NTZ && kind != ValueKind::TIMESTAMP_TZ) { + if (kind != ValueKind::TIMESTAMP_NTZ && kind != ValueKind::TIMESTAMP_NTZ_NANOS && + kind != ValueKind::TIMESTAMP_TZ) { throw Exception(ErrorCode::INVALID_ARGUMENT, "Cannot append Variant value to timestamp path builder"); } + if (target_type == TYPE_TIMESTAMP_NS) { + int64_t nanos = 0; + if (kind == ValueKind::TIMESTAMP_NTZ_NANOS) { + nanos = value.get_timestamp_ntz_nanos(); + } else if (kind != ValueKind::TIMESTAMP_NTZ || + __builtin_mul_overflow(value.get_timestamp_ntz_micros(), + TimeStampNsValue::NANOS_PER_MICROSECOND, &nanos)) { + throw Exception(ErrorCode::INVALID_ARGUMENT, + "Variant timestamp cannot be represented as TIMESTAMP_NS"); + } + assert_cast(*target).insert_value(TimeStampNsValue(nanos)); + return; + } + DORIS_CHECK(kind != ValueKind::TIMESTAMP_NTZ_NANOS); const int64_t micros = kind == ValueKind::TIMESTAMP_NTZ ? value.get_timestamp_ntz_micros() : value.get_timestamp_micros(); cctz::civil_second civil; @@ -751,6 +789,7 @@ void append_value(VariantRef value, const DataTypePtr& target_type, IColumn* tar append_date(value, target); return; case TYPE_DATETIMEV2: + case TYPE_TIMESTAMP_NS: case TYPE_TIMESTAMPTZ: append_timestamp(value, target_type->get_primitive_type(), target); return; diff --git a/be/src/storage/segment/variant/v2/variant_storage_cell.cpp b/be/src/storage/segment/variant/v2/variant_storage_cell.cpp index bd9f3ca3adfce5..311e59fc465ad3 100644 --- a/be/src/storage/segment/variant/v2/variant_storage_cell.cpp +++ b/be/src/storage/segment/variant/v2/variant_storage_cell.cpp @@ -32,6 +32,7 @@ #include "core/data_type/data_type_factory.hpp" #include "core/data_type/storage_field_type.h" #include "core/data_type_serde/data_type_serde.h" +#include "core/value/timestamp_ns_value.h" #include "core/value/variant/variant_parquet_encoding.h" #include "exec/common/format_ip.h" #include "exprs/function/parse/variant_jsonb_parse.h" @@ -133,6 +134,9 @@ Status validate_scalar_cell(BinaryCellCursor& cursor, FieldType field_type, uint case FieldType::OLAP_FIELD_TYPE_TIMESTAMPTZ: RETURN_IF_ERROR(cursor.read(scale, "timestamp scale")); return cursor.skip(sizeof(UInt64), "timestamp value"); + case FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS: + RETURN_IF_ERROR(cursor.read(scale, "timestamp_ns scale")); + return cursor.skip(sizeof(Int64), "timestamp_ns value"); case FieldType::OLAP_FIELD_TYPE_DECIMAL: RETURN_IF_ERROR(cursor.read(precision, "legacy DecimalV2 precision")); RETURN_IF_ERROR(cursor.read(scale, "legacy DecimalV2 scale")); @@ -325,6 +329,15 @@ Status append_binary_value(BinaryCellCursor& cursor, VariantBatchBuilder::Row& o } return Status::OK(); } + case FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS: { + uint8_t scale = 0; + Int64 raw = 0; + RETURN_IF_ERROR(cursor.read(&scale, "timestamp_ns scale")); + RETURN_IF_ERROR(cursor.read(&raw, "timestamp_ns value")); + DORIS_CHECK_EQ(scale, TimeStampNsValue::FRACTIONAL_DIGITS); + output.add_timestamp_nanos(raw, false); + return Status::OK(); + } case FieldType::OLAP_FIELD_TYPE_DECIMAL: { uint8_t precision = 0; uint8_t scale = 0; diff --git a/be/src/storage/tablet/tablet_schema.cpp b/be/src/storage/tablet/tablet_schema.cpp index a1390582d42729..e309266b587a7f 100644 --- a/be/src/storage/tablet/tablet_schema.cpp +++ b/be/src/storage/tablet/tablet_schema.cpp @@ -98,6 +98,8 @@ FieldType TabletColumn::get_field_type_by_string(const std::string& type_str) { type = FieldType::OLAP_FIELD_TYPE_DATEV2; } else if (0 == upper_type_str.compare("DATETIMEV2")) { type = FieldType::OLAP_FIELD_TYPE_DATETIMEV2; + } else if (0 == upper_type_str.compare("TIMESTAMP_NS")) { + type = FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS; } else if (0 == upper_type_str.compare("DATETIME")) { type = FieldType::OLAP_FIELD_TYPE_DATETIME; } else if (0 == upper_type_str.compare("TIMESTAMPTZ")) { @@ -241,6 +243,8 @@ std::string TabletColumn::get_string_by_field_type(FieldType type) { case FieldType::OLAP_FIELD_TYPE_DATETIMEV2: return "DATETIMEV2"; + case FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS: + return "TIMESTAMP_NS"; case FieldType::OLAP_FIELD_TYPE_TIMESTAMPTZ: return "TIMESTAMPTZ"; @@ -356,6 +360,7 @@ uint32_t TabletColumn::get_field_length_by_type(TPrimitiveType::type type, uint3 case TPrimitiveType::DATETIME: return 8; case TPrimitiveType::DATETIMEV2: + case TPrimitiveType::TIMESTAMP_NS: case TPrimitiveType::TIMESTAMPTZ: return 8; case TPrimitiveType::FLOAT: diff --git a/be/src/storage/tablet_info.cpp b/be/src/storage/tablet_info.cpp index 9fee41082442c2..9b6a3fe6ed7699 100644 --- a/be/src/storage/tablet_info.cpp +++ b/be/src/storage/tablet_info.cpp @@ -42,6 +42,7 @@ #include "core/data_type/data_type_factory.hpp" #include "core/data_type/define_primitive_type.h" #include "core/data_type/primitive_type.h" +#include "core/data_type_serde/data_type_timestamp_ns_serde.h" #include "core/value/large_int_value.h" #include "runtime/descriptors.h" #include "runtime/memory/mem_tracker.h" @@ -647,6 +648,13 @@ static Status _create_partition_key(const TExprNode& t_expr, BlockRow* part_key, return Status::InternalError(ss.str()); } column->insert_data(reinterpret_cast(&dt), 0); + } else if (primitive_type == TYPE_TIMESTAMP_NS) { + int64_t epoch_nanos = 0; + RETURN_IF_ERROR(parse_timestamp_ns( + {t_expr.date_literal.value.data(), t_expr.date_literal.value.size()}, + &epoch_nanos)); + const TimeStampNsValue dt(epoch_nanos); + column->insert_data(reinterpret_cast(&dt), 0); } else if (primitive_type == TYPE_TIMESTAMPTZ) { TimestampTzValue res; CastParameters params {.status = Status::OK(), .is_strict = true}; diff --git a/be/src/storage/types.h b/be/src/storage/types.h index 7d66631ef16180..432715b56a01c0 100644 --- a/be/src/storage/types.h +++ b/be/src/storage/types.h @@ -173,6 +173,11 @@ struct CppTypeTraits { using UnsignedCppType = uint64_t; }; template <> +struct CppTypeTraits { + using CppType = int64_t; + using UnsignedCppType = uint64_t; +}; +template <> struct CppTypeTraits { using CppType = uint64_t; using UnsignedCppType = uint64_t; @@ -306,6 +311,9 @@ struct FieldTypeTraits template <> struct FieldTypeTraits : public BaseFieldTypeTraits {}; +template <> +struct FieldTypeTraits + : public BaseFieldTypeTraits {}; template <> struct FieldTypeTraits @@ -421,6 +429,7 @@ inline size_t field_type_size(FieldType field_type) { DORIS_FIELD_TYPE_SIZE_CASE(OLAP_FIELD_TYPE_DATETIME) DORIS_FIELD_TYPE_SIZE_CASE(OLAP_FIELD_TYPE_DATEV2) DORIS_FIELD_TYPE_SIZE_CASE(OLAP_FIELD_TYPE_DATETIMEV2) + DORIS_FIELD_TYPE_SIZE_CASE(OLAP_FIELD_TYPE_TIMESTAMP_NS) DORIS_FIELD_TYPE_SIZE_CASE(OLAP_FIELD_TYPE_TIMEV2) DORIS_FIELD_TYPE_SIZE_CASE(OLAP_FIELD_TYPE_TIMESTAMPTZ) DORIS_FIELD_TYPE_SIZE_CASE(OLAP_FIELD_TYPE_IPV4) diff --git a/be/src/tools/meta_tool.cpp b/be/src/tools/meta_tool.cpp index 18bc27c1d839c2..2c95ce29d9b0f7 100644 --- a/be/src/tools/meta_tool.cpp +++ b/be/src/tools/meta_tool.cpp @@ -386,6 +386,8 @@ std::string get_field_type_string(doris::FieldType type) { return "DATEV2"; case doris::FieldType::OLAP_FIELD_TYPE_DATETIMEV2: return "DATETIMEV2"; + case doris::FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS: + return "TIMESTAMP_NS"; case doris::FieldType::OLAP_FIELD_TYPE_BOOL: return "BOOLEAN"; case doris::FieldType::OLAP_FIELD_TYPE_STRUCT: @@ -513,6 +515,14 @@ std::string format_column_value(const doris::IColumn& column, size_t row, } return ""; } + case FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS: { + const StringRef& data = column.get_data_at(row); + if (data.size == sizeof(int64_t)) { + int64_t val = *reinterpret_cast(data.data); + return std::to_string(val); + } + return ""; + } case FieldType::OLAP_FIELD_TYPE_CHAR: case FieldType::OLAP_FIELD_TYPE_VARCHAR: case FieldType::OLAP_FIELD_TYPE_STRING: diff --git a/be/src/util/raw_value.h b/be/src/util/raw_value.h index 4babb5c0810037..ca9914e4064d9d 100644 --- a/be/src/util/raw_value.h +++ b/be/src/util/raw_value.h @@ -85,7 +85,8 @@ inline uint32_t RawValue::zlib_crc32(const void* v, size_t len, const PrimitiveT return HashUtil::zlib_crc_hash(v, 4, seed); } - case TYPE_DATETIMEV2: { + case TYPE_DATETIMEV2: + case TYPE_TIMESTAMP_NS: { return HashUtil::zlib_crc_hash(v, 8, seed); } diff --git a/be/test/core/column/common_column_test.h b/be/test/core/column/common_column_test.h index 149776b238a485..64734c23c8eeaa 100644 --- a/be/test/core/column/common_column_test.h +++ b/be/test/core/column/common_column_test.h @@ -2767,7 +2767,7 @@ auto assert_column_vector_insert_range_of_integer_callback = [](auto x, const Mu auto* col_vec_target = assert_cast*>(target_column.get()); auto* col_vec_src = assert_cast*>(source_column.get()); if constexpr (std::is_same_v || std::is_same_v || is_date_type(PType) || - PType == TYPE_TIMESTAMPTZ) { + is_timestamp_ns_type(PType) || PType == TYPE_TIMESTAMPTZ) { typename PrimitiveTypeTraits::CppType begin; typename PrimitiveTypeTraits::CppType end; if constexpr (PType == TYPE_DATE || PType == TYPE_DATETIME) { @@ -3038,7 +3038,8 @@ auto assert_column_vector_get_int64_callback = [](auto x, const MutableColumnPtr auto* col_vec_src = assert_cast(source_column.get()); const auto& data = col_vec_src->get_data(); for (size_t i = 0; i != src_size; ++i) { - if constexpr (!IsDecimalNumber && !is_date_type(PType) && PType != TYPE_TIMESTAMPTZ) { + if constexpr (!IsDecimalNumber && !is_date_type(PType) && !is_timestamp_ns_type(PType) && + PType != TYPE_TIMESTAMPTZ) { EXPECT_EQ(col_vec_src->get_int(i), (Int64)data[i]); } } diff --git a/be/test/core/data_type/common_data_type_test.h b/be/test/core/data_type/common_data_type_test.h index 869ab4c33a8dba..f9efaf7e56da01 100644 --- a/be/test/core/data_type/common_data_type_test.h +++ b/be/test/core/data_type/common_data_type_test.h @@ -131,6 +131,7 @@ class CommonDataTypeTest : public ::testing::Test { is_int_or_bool(data_type->get_primitive_type()) || is_float_or_double(data_type->get_primitive_type()) || is_date_type(data_type->get_primitive_type()) || + is_timestamp_ns_type(data_type->get_primitive_type()) || is_ip(data_type->get_primitive_type())) { ASSERT_EQ(data_type->get_size_of_value_in_memory(), meta_info.size_of_value_in_memory); } else { diff --git a/be/test/core/data_type/data_type_datetime_v2_test.cpp b/be/test/core/data_type/data_type_datetime_v2_test.cpp index e1a58ae49a543e..b3aeec27da2e8e 100644 --- a/be/test/core/data_type/data_type_datetime_v2_test.cpp +++ b/be/test/core/data_type/data_type_datetime_v2_test.cpp @@ -120,6 +120,9 @@ TEST_F(DataTypeDateTimeV2Test, simple_func_test) { test_func(dt_time_v2_6); EXPECT_THROW(DataTypeDateTimeV2(7), Exception); EXPECT_THROW(create_datetimev2(7), Exception); + EXPECT_THROW(create_datetimev2(8), Exception); + EXPECT_THROW(create_datetimev2(9), Exception); + EXPECT_THROW(create_datetimev2(10), Exception); EXPECT_THROW(DataTypeTimeV2(7), Exception); } @@ -869,4 +872,4 @@ TEST_F(DataTypeDateTimeV2Test, GetFieldWithDataTypeTest) { field_datetime_v2); } -} // namespace doris \ No newline at end of file +} // namespace doris diff --git a/be/test/core/data_type/data_type_timestamp_ns_test.cpp b/be/test/core/data_type/data_type_timestamp_ns_test.cpp new file mode 100644 index 00000000000000..fd5fc9f6f8db59 --- /dev/null +++ b/be/test/core/data_type/data_type_timestamp_ns_test.cpp @@ -0,0 +1,700 @@ +// 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 "core/data_type/data_type_timestamp_ns.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "core/assert_cast.h" +#include "core/column/column_const.h" +#include "core/column/column_nullable.h" +#include "core/column/column_string.h" +#include "core/data_type/data_type_date_or_datetime_v2.h" +#include "core/data_type_serde/data_type_serde.h" +#include "core/data_type_serde/data_type_timestamp_ns_serde.h" +#include "core/string_buffer.hpp" +#include "core/value/vdatetime_value.h" +#include "exprs/function/cast/cast_parameters.h" +#include "util/jsonb_utils.h" +#include "util/jsonb_writer.h" +#include "util/mysql_row_buffer.h" +#include "util/slice.h" +#include "util/timezone_utils.h" + +namespace doris { + +TEST(DataTypeTimeStampNsTest, TypeFamilyClassifiersKeepTimestampNsIndependent) { + EXPECT_FALSE(is_date_type(TYPE_TIMESTAMP_NS)); + EXPECT_TRUE(is_timestamp_ns_type(TYPE_TIMESTAMP_NS)); + EXPECT_FALSE(is_timestamp_ns_type(TYPE_DATETIMEV2)); + + EXPECT_TRUE(is_date_v2_or_datetime_v2(TYPE_DATEV2)); + EXPECT_TRUE(is_date_v2_or_datetime_v2(TYPE_DATETIMEV2)); + EXPECT_FALSE(is_date_v2_or_datetime_v2(TYPE_TIMESTAMP_NS)); + + EXPECT_TRUE(IsDataTypeDateTimeV2); + EXPECT_FALSE(IsDataTypeDateTimeV2); +} + +TEST(DataTypeTimeStampNsTest, Int64EpochRangeAndOrdering) { + const TimeStampNsValue epoch(0); + const TimeStampNsValue before_epoch(-1); + const TimeStampNsValue minimum(std::numeric_limits::min()); + const TimeStampNsValue maximum(std::numeric_limits::max()); + + EXPECT_EQ(epoch.to_string(), "1970-01-01 00:00:00.000000000"); + EXPECT_EQ(before_epoch.to_string(), "1969-12-31 23:59:59.999999999"); + EXPECT_EQ(minimum.to_string(), "1677-09-21 00:12:43.145224192"); + EXPECT_EQ(maximum.to_string(), "2262-04-11 23:47:16.854775807"); + EXPECT_LT(minimum, before_epoch); + EXPECT_LT(before_epoch, epoch); + EXPECT_LT(epoch, maximum); +} + +TEST(DataTypeTimeStampNsTest, NegativeEpochUsesFloorSecondAndNormalizedFraction) { + struct TestCase { + int64_t epoch_nanos; + int64_t epoch_seconds; + uint32_t nanosecond; + }; + const std::vector cases = { + {-1000000001, -2, 999999999}, + {-1000000000, -1, 0}, + {-999999999, -1, 1}, + {-1, -1, 999999999}, + {0, 0, 0}, + {1, 0, 1}, + }; + + for (const auto& test_case : cases) { + const TimeStampNsValue value(test_case.epoch_nanos); + EXPECT_EQ(value.epoch_seconds(), test_case.epoch_seconds); + EXPECT_EQ(value.nanosecond(), test_case.nanosecond); + EXPECT_EQ( + static_cast<__int128>(value.epoch_seconds()) * TimeStampNsValue::NANOS_PER_SECOND + + value.nanosecond(), + test_case.epoch_nanos); + } +} + +TEST(DataTypeTimeStampNsTest, ParseAtFixedNanosecondPrecision) { + int64_t value = 0; + + ASSERT_TRUE(parse_timestamp_ns(StringRef("1970-01-01 00:00:00.12345675"), &value).ok()); + EXPECT_EQ(TimeStampNsValue(value).to_string(), "1970-01-01 00:00:00.123456750"); + + ASSERT_TRUE(parse_timestamp_ns(StringRef("1969-12-31 23:59:59.999999999"), &value).ok()); + EXPECT_EQ(value, -1); + + ASSERT_TRUE(parse_timestamp_ns(StringRef("1970-01-01 00:00:00.999999995"), &value).ok()); + EXPECT_EQ(TimeStampNsValue(value).to_string(), "1970-01-01 00:00:00.999999995"); + + ASSERT_TRUE(parse_timestamp_ns(StringRef("1970-01-01 00:00:00.9999999995"), &value).ok()); + EXPECT_EQ(TimeStampNsValue(value).to_string(), "1970-01-01 00:00:01.000000000"); +} + +TEST(DataTypeTimeStampNsTest, ParseTimezoneSuffixInSessionTimezone) { + TimezoneUtils::load_timezones_to_cache(); + cctz::time_zone shanghai; + ASSERT_TRUE(cctz::load_time_zone("Asia/Shanghai", &shanghai)); + + int64_t value = 0; + auto status = + parse_timestamp_ns(StringRef("2023-08-17T01:41:18.123456789Z"), &value, &shanghai); + ASSERT_TRUE(status.ok()) << status.to_string(); + EXPECT_EQ(TimeStampNsValue(value).to_string(), "2023-08-17 09:41:18.123456789"); + + ASSERT_TRUE(parse_timestamp_ns(StringRef("2023-08-17T01:41:18.123456789America/Los_Angeles"), + &value, &shanghai) + .ok()); + EXPECT_EQ(TimeStampNsValue(value).to_string(), "2023-08-17 16:41:18.123456789"); + + EXPECT_FALSE( + parse_timestamp_ns(StringRef("1677-09-21T00:12:43.145224192+14:00"), &value, &shanghai) + .ok()); + EXPECT_FALSE( + parse_timestamp_ns(StringRef("2262-04-11T23:47:16.854775807-01:00"), &value, &shanghai) + .ok()); +} + +TEST(DataTypeTimeStampNsTest, ParseAcceptsFractionalWidthsAndRejectsMalformedValues) { + struct ValidCase { + const char* input; + const char* expected; + }; + const std::vector valid_cases = { + {"2024-02-29 12:34:56.1234567", "2024-02-29 12:34:56.123456700"}, + {"2024-02-29 12:34:56.12345678", "2024-02-29 12:34:56.123456780"}, + {"2024-02-29 12:34:56.123456789", "2024-02-29 12:34:56.123456789"}, + {"2024-02-29 12:34:56.1234567894", "2024-02-29 12:34:56.123456789"}, + {"2024-02-29 12:34:56.1234567895", "2024-02-29 12:34:56.123456790"}, + {"2024-02-29 12:34:56", "2024-02-29 12:34:56.000000000"}, + }; + + for (const auto& test_case : valid_cases) { + int64_t value = 0; + ASSERT_TRUE(parse_timestamp_ns(StringRef(test_case.input), &value).ok()) << test_case.input; + EXPECT_EQ(TimeStampNsValue(value).to_string(), test_case.expected); + } + + const std::vector invalid_values = { + "", + "not-a-date", + "2023-02-29 00:00:00.000000000", + "2024-13-01", + "2024-01-01 24:00:00", + "2024-01-01 00:00:00.trailing", + "2024-01-01 00:00:00.123.456", + "2024-01-01.123 00:00:00", + "2024.01-01 00:00:00", + }; + for (const char* input : invalid_values) { + int64_t value = 0; + EXPECT_FALSE(parse_timestamp_ns(StringRef(input), &value).ok()) << input; + } +} + +TEST(DataTypeTimeStampNsTest, RejectValuesOutsideEpochRange) { + int64_t value = 0; + EXPECT_FALSE(parse_timestamp_ns(StringRef("0000-01-01 00:00:00.000000000"), &value).ok()); + EXPECT_FALSE(parse_timestamp_ns(StringRef("1677-09-21 00:12:43.145224191"), &value).ok()); + EXPECT_FALSE(parse_timestamp_ns(StringRef("2262-04-11 23:47:16.854775808"), &value).ok()); + EXPECT_FALSE(parse_timestamp_ns(StringRef("9999-12-31 23:59:59.999999999"), &value).ok()); +} + +TEST(DataTypeTimeStampNsTest, CivilRoundTripPreservesSubMicrosecondDigits) { + DateV2Value civil; + civil.unchecked_set_time(2024, 2, 29, 23, 59, 58, 123456); + + TimeStampNsValue value; + ASSERT_TRUE(value.from_datetime(civil, 789)); + EXPECT_EQ(value.to_string(), "2024-02-29 23:59:58.123456789"); + const auto round_trip = value.to_datetime(); + EXPECT_EQ(round_trip.year(), 2024); + EXPECT_EQ(round_trip.month(), 2); + EXPECT_EQ(round_trip.day(), 29); + EXPECT_EQ(round_trip.hour(), 23); + EXPECT_EQ(round_trip.minute(), 59); + EXPECT_EQ(round_trip.second(), 58); + EXPECT_EQ(value.microsecond(), 123456); + EXPECT_EQ(value.nanosecond_remainder(), 789); + EXPECT_EQ(round_trip.to_date_int_val(), civil.to_date_int_val()); +} + +TEST(DataTypeTimeStampNsTest, FactoryKeepsTimestampNsSeparateFromDateTimeV2) { + const auto microseconds = create_datetimev2(6); + const auto timestamp_ns = std::make_shared(); + + EXPECT_EQ(microseconds->get_primitive_type(), TYPE_DATETIMEV2); + EXPECT_THROW(create_datetimev2(7), Exception); + EXPECT_THROW(create_datetimev2(8), Exception); + EXPECT_THROW(create_datetimev2(9), Exception); + EXPECT_EQ(timestamp_ns->get_primitive_type(), TYPE_TIMESTAMP_NS); + EXPECT_EQ(timestamp_ns->get_storage_field_type(), FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS); + EXPECT_EQ(timestamp_ns->get_scale(), 9); + EXPECT_EQ(microseconds->get_family_name(), "DateTimeV2"); + EXPECT_EQ(timestamp_ns->get_family_name(), "TimeStampNs"); +} + +TEST(DataTypeTimeStampNsTest, SerDeRoundTripsTextProtobufAndBinary) { + const auto type = std::make_shared(); + const auto serde = type->get_serde(); + auto source = type->create_column(); + DataTypeSerDe::FormatOptions options; + const std::vector inputs = { + "1677-09-21 00:12:43.145224192", "1969-12-31 23:59:59.999999999", + "1970-01-01 00:00:00.000000000", "2024-02-29 12:34:56.123456789", + "2262-04-11 23:47:16.854775807", + }; + for (const auto& input : inputs) { + StringRef ref(input); + ASSERT_TRUE(serde->from_string(ref, *source, options).ok()) << input; + } + const auto& source_data = assert_cast(*source).get_data(); + + PValues protobuf_values; + ASSERT_TRUE(serde->write_column_to_pb(*source, protobuf_values, 0, source->size()).ok()); + auto protobuf_result = type->create_column(); + ASSERT_TRUE(serde->read_column_from_pb(*protobuf_result, protobuf_values).ok()); + const auto& protobuf_data = assert_cast(*protobuf_result).get_data(); + EXPECT_EQ(protobuf_data, source_data); + + ColumnString::Chars binary; + std::vector offsets = {0}; + for (size_t row = 0; row < source->size(); ++row) { + serde->write_one_cell_to_binary(*source, binary, row); + offsets.push_back(binary.size()); + } + constexpr size_t bytes_per_row = sizeof(uint8_t) + sizeof(uint8_t) + sizeof(int64_t); + ASSERT_EQ(binary.size(), source->size() * bytes_per_row); + auto binary_result = ColumnNullable::create(type->create_column(), ColumnUInt8::create()); + for (size_t row = 0; row < source->size(); ++row) { + const uint8_t* begin = binary.data() + offsets[row]; + const uint8_t* end = DataTypeSerDe::deserialize_binary_to_column(begin, *binary_result); + EXPECT_EQ(end - begin, bytes_per_row); + } + const auto& binary_data = + assert_cast(binary_result->get_nested_column()).get_data(); + EXPECT_EQ(binary_data, source_data); +} + +TEST(DataTypeTimeStampNsTest, SerDeRoundTripsArrowNanosecondsBeforeEpoch) { + const auto type = std::make_shared(); + const auto serde = type->get_serde(); + auto source = type->create_column(); + auto& source_data = assert_cast(*source).get_data(); + source_data.push_back(TimeStampNsValue(-1)); + source_data.push_back(TimeStampNsValue(0)); + source_data.push_back(TimeStampNsValue(1234567890)); + + arrow::TimestampBuilder builder(arrow::timestamp(arrow::TimeUnit::NANO), + arrow::default_memory_pool()); + ASSERT_TRUE(serde->write_column_to_arrow(*source, nullptr, &builder, 0, source->size(), + cctz::utc_time_zone()) + .ok()); + std::shared_ptr array; + ASSERT_TRUE(builder.Finish(&array).ok()); + const auto* timestamps = assert_cast(array.get()); + EXPECT_EQ(timestamps->Value(0), -1); + EXPECT_EQ(timestamps->Value(1), 0); + EXPECT_EQ(timestamps->Value(2), 1234567890); + + auto result = type->create_column(); + ASSERT_TRUE(serde->read_column_from_arrow(*result, array.get(), 0, array->length(), + cctz::utc_time_zone()) + .ok()); + EXPECT_EQ(assert_cast(*result).get_data(), source_data); +} + +TEST(DataTypeTimeStampNsTest, DecodedTimestampUnitsAndValidation) { + const auto type = std::make_shared(); + const auto serde = type->get_serde(); + const int64_t values[] = {-1, 0, 1}; + + const auto check_unit = [&](DecodedTimeUnit unit, int64_t multiplier) { + auto column = type->create_column(); + DecodedColumnView view; + view.value_kind = DecodedValueKind::INT64; + view.time_unit = unit; + view.row_count = 3; + view.values = reinterpret_cast(values); + ASSERT_TRUE(serde->read_column_from_decoded_values(*column, view).ok()); + const auto& data = assert_cast(*column).get_data(); + ASSERT_EQ(data.size(), 3); + EXPECT_EQ(data[0].epoch_nanos(), -multiplier); + EXPECT_EQ(data[1].epoch_nanos(), 0); + EXPECT_EQ(data[2].epoch_nanos(), multiplier); + }; + + check_unit(DecodedTimeUnit::MILLIS, TimeStampNsValue::NANOS_PER_MILLISECOND); + check_unit(DecodedTimeUnit::MICROS, TimeStampNsValue::NANOS_PER_MICROSECOND); + check_unit(DecodedTimeUnit::NANOS, 1); + + { + auto column = type->create_column(); + DecodedColumnView view; + view.value_kind = DecodedValueKind::INT64; + view.time_unit = DecodedTimeUnit::UNKNOWN; + view.row_count = 3; + view.values = reinterpret_cast(values); + EXPECT_FALSE(serde->read_column_from_decoded_values(*column, view).ok()); + } + + { + const int64_t overflow = std::numeric_limits::max(); + auto column = type->create_column(); + DecodedColumnView view; + view.value_kind = DecodedValueKind::INT64; + view.time_unit = DecodedTimeUnit::MILLIS; + view.row_count = 1; + view.values = reinterpret_cast(&overflow); + EXPECT_FALSE(serde->read_column_from_decoded_values(*column, view).ok()); + } +} + +TEST(DataTypeTimeStampNsTest, DataTypeLiteralField) { + const DataTypeTimeStampNs type; + const DataTypeDateTimeV2 legacy6(6); + + EXPECT_TRUE(type.equals(DataTypeTimeStampNs {})); + EXPECT_FALSE(type.equals(legacy6)); + EXPECT_FALSE(type.equals_ignore_precision(legacy6)); + EXPECT_FALSE(legacy6.equals_ignore_precision(type)); + + TExprNode node; + node.date_literal.value = "2024-02-29 12:34:56.123456789"; + const Field field = type.get_field(node); + EXPECT_EQ(field.get().to_string(), "2024-02-29 12:34:56.123456789"); + EXPECT_EQ(field.to_debug_string(0), "2024-02-29 12:34:56.123456789"); + EXPECT_EQ(field.to_debug_string(6), "2024-02-29 12:34:56.123456789"); + node.date_literal.value = "not-a-datetime"; + EXPECT_THROW(type.get_field(node), Exception); + + auto column = type.create_column(); + column->insert(field); + const auto field_with_type = type.get_field_with_data_type(*column, 0); + EXPECT_EQ(field_with_type.field, field); + EXPECT_EQ(field_with_type.base_scalar_type_id, TYPE_TIMESTAMP_NS); + EXPECT_EQ(field_with_type.precision, -1); + EXPECT_EQ(field_with_type.scale, 9); +} + +TEST(DataTypeTimeStampNsTest, FormattingAndHash) { + int64_t raw = 0; + ASSERT_TRUE(parse_timestamp_ns(StringRef("2024-02-29 12:34:56.123456789"), &raw).ok()); + TimeStampNsValue value(raw); + + EXPECT_TRUE(value.is_valid_date()); + + char text[40] = {}; + const char* end = value.to_string(text); + EXPECT_STREQ(text, "2024-02-29 12:34:56.123456789"); + EXPECT_EQ(end, text + std::strlen(text) + 1); + + EXPECT_EQ(value.hash(17), value.hash(17)); + EXPECT_EQ(std::hash {}(value), std::hash {}(value.epoch_nanos())); +} + +TEST(DataTypeTimeStampNsTest, SerDeStrictBatchJsonJsonbMysqlAndBinaryField) { + const DataTypeTimeStampNs type; + const auto serde = type.get_serde(); + DataTypeSerDe::FormatOptions options; + options.field_delim = ";"; + + auto strings = ColumnString::create(); + strings->insert_data("1970-01-01 00:00:00.000000001", 29); + strings->insert_data("ignored-invalid-value", 21); + strings->insert_data("2024-02-29 12:34:56.123456789", 29); + NullMap null_map = {0, 1, 0}; + auto strict_result = type.create_column(); + ASSERT_TRUE( + serde->from_string_strict_mode_batch(*strings, *strict_result, options, null_map.data()) + .ok()); + const auto& strict_data = assert_cast(*strict_result).get_data(); + EXPECT_EQ(strict_data[0].epoch_nanos(), 1); + EXPECT_EQ(strict_data[2].to_string(), "2024-02-29 12:34:56.123456789"); + + auto invalid_strings = ColumnString::create(); + invalid_strings->insert_data("invalid", 7); + auto invalid_result = type.create_column(); + EXPECT_FALSE(serde->from_string_strict_mode_batch(*invalid_strings, *invalid_result, options, + nullptr) + .ok()); + + auto source = type.create_column(); + for (const std::string input : + {"1970-01-01 00:00:00.000000001", "2024-02-29 12:34:56.123456789"}) { + StringRef ref(input); + ASSERT_TRUE(serde->from_string_strict_mode(ref, *source, options).ok()); + } + + auto serialized = ColumnString::create(); + VectorBufferWriter writer(*serialized); + ASSERT_TRUE(serde->serialize_column_to_json(*source, 0, source->size(), writer, options).ok()); + writer.commit(); + EXPECT_EQ(serialized->get_data_at(0).to_string(), + "1970-01-01 00:00:00.000000001;2024-02-29 12:34:56.123456789"); + + std::vector json_values = {"1970-01-01 00:00:00.000000001", + "2024-02-29 12:34:56.123456789"}; + std::vector slices; + for (auto& json_value : json_values) { + slices.emplace_back(json_value.data(), json_value.size()); + } + auto json_result = type.create_column(); + uint64_t num_deserialized = 0; + ASSERT_TRUE(serde->deserialize_column_from_json_vector(*json_result, slices, &num_deserialized, + options) + .ok()); + EXPECT_EQ(num_deserialized, json_values.size()); + EXPECT_EQ(assert_cast(*json_result).get_data(), + assert_cast(*source).get_data()); + + const auto nested_serde = type.get_serde(2); + auto nested_json = ColumnString::create(); + VectorBufferWriter nested_writer(*nested_json); + ASSERT_TRUE(nested_serde->serialize_one_cell_to_json(*source, 1, nested_writer, options).ok()); + nested_writer.commit(); + EXPECT_EQ(nested_json->get_data_at(0).to_string(), "\"2024-02-29 12:34:56.123456789\""); + auto nested_result = type.create_column(); + std::string quoted = nested_json->get_data_at(0).to_string(); + Slice quoted_slice(quoted.data(), quoted.size()); + ASSERT_TRUE(nested_serde->deserialize_one_cell_from_json(*nested_result, quoted_slice, options) + .ok()); + EXPECT_EQ(assert_cast(*nested_result).get_element(0), + assert_cast(*source).get_element(1)); + + auto one_value = source->clone_resized(1); + auto const_column = ColumnConst::create(std::move(one_value), 2); + auto const_json = ColumnString::create(); + VectorBufferWriter const_writer(*const_json); + ASSERT_TRUE(serde->serialize_one_cell_to_json(*const_column, 1, const_writer, options).ok()); + const_writer.commit(); + EXPECT_EQ(const_json->get_data_at(0).to_string(), "1970-01-01 00:00:00.000000001"); + + JsonbWriter jsonb_writer; + ASSERT_TRUE(serde->serialize_column_to_jsonb(*source, 1, jsonb_writer).ok()); + EXPECT_EQ(JsonbToJson::jsonb_to_json_string(jsonb_writer.getOutput()->getBuffer(), + jsonb_writer.getOutput()->getSize()), + "\"2024-02-29 12:34:56.123456789\""); + CastParameters cast_params {.status = Status::OK(), .is_strict = true}; + auto jsonb_result = type.create_column(); + ASSERT_TRUE(serde->deserialize_column_from_jsonb(*jsonb_result, jsonb_writer.getValue(), + cast_params) + .ok()); + EXPECT_EQ(assert_cast(*jsonb_result).get_element(0), + assert_cast(*source).get_element(1)); + + auto jsonb_values = ColumnString::create(); + ASSERT_TRUE(serde->serialize_column_to_jsonb_vector(*source, *jsonb_values).ok()); + auto jsonb_vector_result = ColumnNullable::create(type.create_column(), ColumnUInt8::create()); + ASSERT_TRUE(serde->deserialize_column_from_jsonb_vector(*jsonb_vector_result, *jsonb_values, + cast_params) + .ok()); + EXPECT_EQ(assert_cast(jsonb_vector_result->get_nested_column()) + .get_data(), + assert_cast(*source).get_data()); + + JsonbWriter row_store_writer; + Arena row_store_arena; + row_store_writer.writeStartObject(); + serde->write_one_cell_to_jsonb(*source, row_store_writer, row_store_arena, 0, 1, options); + row_store_writer.writeEndObject(); + const JsonbDocument* row_store_document = nullptr; + ASSERT_TRUE(JsonbDocument::checkAndCreateDocument(row_store_writer.getOutput()->getBuffer(), + row_store_writer.getOutput()->getSize(), + &row_store_document) + .ok()); + auto row_store_result = type.create_column(); + serde->read_one_cell_from_jsonb(*row_store_result, (*row_store_document)->begin()->value()); + EXPECT_EQ(assert_cast(*row_store_result).get_element(0), + assert_cast(*source).get_element(1)); + + MysqlRowBinaryBuffer mysql_buffer; + ASSERT_TRUE(serde->write_column_to_mysql_binary(*source, mysql_buffer, 1, false, options).ok()); + ASSERT_EQ(static_cast(mysql_buffer.buf()[0]), 29); + EXPECT_EQ(std::string(mysql_buffer.buf() + 1, 29), "2024-02-29 12:34:56.123456789"); + + ColumnString::Chars binary; + serde->write_one_cell_to_binary(*source, binary, 1); + Field binary_field; + FieldInfo info; + const uint8_t* end = + DataTypeSerDe::deserialize_binary_to_field(binary.data(), binary_field, info); + EXPECT_EQ(end, binary.data() + binary.size()); + EXPECT_EQ(info.scalar_type_id, TYPE_TIMESTAMP_NS); + EXPECT_EQ(info.scale, 9); + EXPECT_EQ(binary_field.get().to_string(), "2024-02-29 12:34:56.123456789"); +} + +TEST(DataTypeTimeStampNsTest, SerDeBatchRejectsMultipleFractionalSeparators) { + const DataTypeTimeStampNs type; + const auto serde = type.get_serde(); + DataTypeSerDe::FormatOptions options; + + auto strings = ColumnString::create(); + strings->insert_data("2024-01-01 00:00:00.123456789", 29); + strings->insert_data("2024-01-01 00:00:00.123.456", 27); + + auto permissive_result = ColumnNullable::create(type.create_column(), ColumnUInt8::create()); + ASSERT_TRUE(serde->from_string_batch(*strings, *permissive_result, options).ok()); + const auto& permissive_null_map = permissive_result->get_null_map_data(); + ASSERT_EQ(permissive_null_map.size(), 2); + EXPECT_EQ(permissive_null_map[0], 0); + EXPECT_EQ(permissive_null_map[1], 1); + + auto invalid_string = ColumnString::create(); + invalid_string->insert_data("2024-01-01 00:00:00.123.456", 27); + auto strict_result = type.create_column(); + EXPECT_FALSE( + serde->from_string_strict_mode_batch(*invalid_string, *strict_result, options, nullptr) + .ok()); +} + +TEST(DataTypeTimeStampNsTest, SerDeArrowUnitsNullTimezoneAndErrors) { + TimezoneUtils::load_timezones_to_cache(); + cctz::time_zone shanghai; + ASSERT_TRUE(TimezoneUtils::find_cctz_time_zone("Asia/Shanghai", shanghai)); + + const DataTypeTimeStampNs type; + const auto serde = type.get_serde(); + auto source = type.create_column(); + DataTypeSerDe::FormatOptions options; + for (const std::string input : + {"1970-01-01 08:00:01.000000000", "1970-01-01 08:00:02.000000000"}) { + StringRef ref(input); + ASSERT_TRUE(serde->from_string(ref, *source, options).ok()); + } + const NullMap null_map = {0, 1}; + + const std::array, 4> units = { + std::pair {arrow::TimeUnit::SECOND, 1LL}, + std::pair {arrow::TimeUnit::MILLI, 1000LL}, + std::pair {arrow::TimeUnit::MICRO, 1000000LL}, + std::pair {arrow::TimeUnit::NANO, 1000000000LL}, + }; + for (const auto& [unit, multiplier] : units) { + arrow::TimestampBuilder builder(arrow::timestamp(unit, "Asia/Shanghai"), + arrow::default_memory_pool()); + ASSERT_TRUE(serde->write_column_to_arrow(*source, &null_map, &builder, 0, source->size(), + shanghai) + .ok()); + std::shared_ptr array; + ASSERT_TRUE(builder.Finish(&array).ok()); + const auto& timestamps = assert_cast(*array); + EXPECT_EQ(timestamps.Value(0), multiplier); + EXPECT_TRUE(timestamps.IsNull(1)); + + auto result = type.create_column(); + ASSERT_TRUE(serde->read_column_from_arrow(*result, array.get(), 0, 1, shanghai).ok()); + EXPECT_EQ(assert_cast(*result).get_element(0), + assert_cast(*source).get_element(0)); + } + + arrow::Int64Builder wrong_builder; + ASSERT_TRUE(wrong_builder.Append(1).ok()); + std::shared_ptr wrong_array; + ASSERT_TRUE(wrong_builder.Finish(&wrong_array).ok()); + auto wrong_result = type.create_column(); + EXPECT_FALSE( + serde->read_column_from_arrow(*wrong_result, wrong_array.get(), 0, 1, shanghai).ok()); + + for (const auto unit : + {arrow::TimeUnit::SECOND, arrow::TimeUnit::MILLI, arrow::TimeUnit::MICRO}) { + arrow::TimestampBuilder overflow_builder(arrow::timestamp(unit), + arrow::default_memory_pool()); + ASSERT_TRUE(overflow_builder.Append(std::numeric_limits::max()).ok()); + std::shared_ptr overflow_array; + ASSERT_TRUE(overflow_builder.Finish(&overflow_array).ok()); + auto overflow_result = type.create_column(); + EXPECT_FALSE(serde->read_column_from_arrow(*overflow_result, overflow_array.get(), 0, 1, + cctz::utc_time_zone()) + .ok()); + } + + arrow::TimestampBuilder boundary_builder( + arrow::timestamp(arrow::TimeUnit::NANO, "Asia/Shanghai"), arrow::default_memory_pool()); + ASSERT_TRUE(boundary_builder.Append(std::numeric_limits::max()).ok()); + std::shared_ptr boundary_array; + ASSERT_TRUE(boundary_builder.Finish(&boundary_array).ok()); + auto boundary_result = type.create_column(); + EXPECT_FALSE( + serde->read_column_from_arrow(*boundary_result, boundary_array.get(), 0, 1, shanghai) + .ok()); + + auto minimum = type.create_column(); + assert_cast(*minimum).insert_value( + TimeStampNsValue(std::numeric_limits::min())); + arrow::TimestampBuilder minimum_builder( + arrow::timestamp(arrow::TimeUnit::NANO, "Asia/Shanghai"), arrow::default_memory_pool()); + EXPECT_FALSE( + serde->write_column_to_arrow(*minimum, nullptr, &minimum_builder, 0, 1, shanghai).ok()); +} + +TEST(DataTypeTimeStampNsTest, SerDeDecodedNullTimezoneAndOrc) { + TimezoneUtils::load_timezones_to_cache(); + cctz::time_zone shanghai; + ASSERT_TRUE(TimezoneUtils::find_cctz_time_zone("Asia/Shanghai", shanghai)); + + const DataTypeTimeStampNs type; + const auto serde = type.get_serde(); + const int64_t values[] = {0, 1}; + const NullMap null_map = {0, 1}; + DecodedColumnView view; + view.value_kind = DecodedValueKind::INT64; + view.time_unit = DecodedTimeUnit::NANOS; + view.row_count = 2; + view.values = reinterpret_cast(values); + view.null_map = null_map.data(); + view.timestamp_is_adjusted_to_utc = true; + view.timezone = &shanghai; + auto decoded = type.create_column(); + ASSERT_TRUE(serde->read_column_from_decoded_values(*decoded, view).ok()); + const auto& decoded_data = assert_cast(*decoded).get_data(); + EXPECT_EQ(decoded_data[0].to_string(), "1970-01-01 08:00:00.000000000"); + EXPECT_EQ(decoded_data[1].epoch_nanos(), 0); + + view.value_kind = DecodedValueKind::INT32; + auto invalid_kind = type.create_column(); + EXPECT_FALSE(serde->read_column_from_decoded_values(*invalid_kind, view).ok()); + + auto source = type.create_column(); + int64_t source_raw = 0; + ASSERT_TRUE(parse_timestamp_ns(StringRef("1970-01-01 08:00:01.123456789"), &source_raw).ok()); + assert_cast(*source).insert_value(TimeStampNsValue(source_raw)); + assert_cast(*source).insert_value(TimeStampNsValue(0)); + + Arena arena; + DataTypeSerDe::FormatOptions options; + orc::TimestampVectorBatch batch(2, *orc::getDefaultPool()); + batch.resize(2); + batch.notNull[0] = 1; + batch.notNull[1] = 0; + batch.hasNulls = true; + ASSERT_TRUE(serde->write_column_to_orc("Asia/Shanghai", *source, nullptr, &batch, 0, 2, arena, + options) + .ok()); + EXPECT_EQ(batch.numElements, 2); + EXPECT_EQ(batch.data[0], 1); + EXPECT_EQ(batch.nanoseconds[0], 123456789); + EXPECT_EQ(batch.data[1], 0); + EXPECT_FALSE(serde->write_column_to_orc("invalid/timezone", *source, nullptr, &batch, 0, 2, + arena, options) + .ok()); + + auto minimum = type.create_column(); + assert_cast(*minimum).insert_value( + TimeStampNsValue(std::numeric_limits::min())); + orc::TimestampVectorBatch minimum_batch(1, *orc::getDefaultPool()); + minimum_batch.resize(1); + minimum_batch.notNull[0] = 1; + EXPECT_TRUE(serde->write_column_to_orc("Asia/Shanghai", *minimum, nullptr, &minimum_batch, 0, 1, + arena, options) + .ok()); + + const auto orc_type = + std::unique_ptr<::orc::Type>(::orc::Type::buildTypeFromString("timestamp")); + OrcDecodedColumnView orc_view {.file_type = orc_type.get(), + .selected_type = orc_type.get(), + .batch = &batch, + .rows = 2, + .timezone = &shanghai}; + auto orc_result = type.create_column(); + ASSERT_TRUE(serde->read_column_from_orc(*orc_result, orc_view).ok()); + const auto& orc_data = assert_cast(*orc_result).get_data(); + ASSERT_EQ(orc_data.size(), 2); + EXPECT_EQ(orc_data[0].to_string(), "1970-01-01 08:00:01.123456789"); + EXPECT_EQ(orc_data[1].epoch_nanos(), 0); + + batch.nanoseconds[0] = TimeStampNsValue::NANOS_PER_SECOND; + auto invalid_orc_result = type.create_column(); + EXPECT_TRUE(serde->read_column_from_orc(*invalid_orc_result, orc_view) + .is()); + EXPECT_EQ(invalid_orc_result->size(), 0); +} + +} // namespace doris diff --git a/be/test/core/data_type/storage_field_type_test.cpp b/be/test/core/data_type/storage_field_type_test.cpp index af621ceb9c6abe..f2f40f2a265429 100644 --- a/be/test/core/data_type/storage_field_type_test.cpp +++ b/be/test/core/data_type/storage_field_type_test.cpp @@ -72,6 +72,7 @@ constexpr std::array supported_mappings { TypePair {PrimitiveType::TYPE_UINT32, FieldType::OLAP_FIELD_TYPE_UNSIGNED_INT}, TypePair {PrimitiveType::TYPE_UINT64, FieldType::OLAP_FIELD_TYPE_UNSIGNED_BIGINT}, TypePair {PrimitiveType::TYPE_TIMESTAMPTZ, FieldType::OLAP_FIELD_TYPE_TIMESTAMPTZ}, + TypePair {PrimitiveType::TYPE_TIMESTAMP_NS, FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS}, }; TEST(StorageFieldTypeTest, SupportedMappingsRoundTrip) { @@ -90,7 +91,6 @@ TEST(StorageFieldTypeTest, UnsupportedPrimitiveTypesThrow) { static_cast(33), // TYPE_LAMBDA_FUNCTION (deprecated) PrimitiveType::TYPE_FIXED_LENGTH_OBJECT, PrimitiveType::TYPE_VARBINARY, - static_cast(43), static_cast(255), }; @@ -107,7 +107,6 @@ TEST(StorageFieldTypeTest, UnsupportedOrInvalidFieldTypesThrow) { FieldType::OLAP_FIELD_TYPE_DISCRETE_DOUBLE, static_cast(-1), static_cast(0), - static_cast(41), static_cast(255), }; @@ -159,6 +158,7 @@ TEST(StorageFieldTypeTest, PersistedFieldTypeValuesStayStable) { FieldType::OLAP_FIELD_TYPE_IPV4, FieldType::OLAP_FIELD_TYPE_IPV6, FieldType::OLAP_FIELD_TYPE_TIMESTAMPTZ, + FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS, }; for (size_t i = 0; i < persisted_types.size(); ++i) { diff --git a/be/test/core/data_type_serde/data_type_serde_decoded_values_test.cpp b/be/test/core/data_type_serde/data_type_serde_decoded_values_test.cpp index 18e4aa8a1cf848..1303fa1e29a032 100644 --- a/be/test/core/data_type_serde/data_type_serde_decoded_values_test.cpp +++ b/be/test/core/data_type_serde/data_type_serde_decoded_values_test.cpp @@ -830,7 +830,7 @@ TEST(DataTypeSerDeDecodedValuesTest, ReadDateTimeV2Millis) { "1970-01-01 00:00:00.001000", "1970-01-01 00:00:01.234000"}); } -TEST(DataTypeSerDeDecodedValuesTest, ReadDateTimeV2Nanos) { +TEST(DataTypeSerDeDecodedValuesTest, ReadTimeStampNss) { auto type = std::make_shared(6); std::vector values = {-1000, 0, 1000, 1234567890}; auto view = make_fixed_view(DecodedValueKind::INT64, values); diff --git a/be/test/core/data_type_serde/data_type_serde_parquet_test.cpp b/be/test/core/data_type_serde/data_type_serde_parquet_test.cpp index b7b664c7c78de2..6a6ab20a85ead9 100644 --- a/be/test/core/data_type_serde/data_type_serde_parquet_test.cpp +++ b/be/test/core/data_type_serde/data_type_serde_parquet_test.cpp @@ -33,9 +33,11 @@ #include "core/data_type/data_type_number.h" #include "core/data_type/data_type_string.h" #include "core/data_type/data_type_time.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/data_type/data_type_timestamptz.h" #include "core/data_type/data_type_varbinary.h" #include "core/data_type_serde/parquet_decode_source.h" +#include "util/timezone_utils.h" namespace doris { namespace { @@ -273,6 +275,8 @@ TEST(DataTypeSerDeParquetTest, RawPredicateConversionSupportsEveryFixedLogicalFa DataTypeDateTimeV2(6).get_serde()->supports_parquet_raw_predicate(timestamp_context)); EXPECT_TRUE( DataTypeTimeStampTz(6).get_serde()->supports_parquet_raw_predicate(timestamp_context)); + EXPECT_TRUE( + DataTypeTimeStampNs().get_serde()->supports_parquet_raw_predicate(timestamp_context)); ParquetDecodeContext time_context {.physical_type = ParquetPhysicalType::INT64, .logical_type = ParquetLogicalType::TIME, @@ -698,6 +702,136 @@ TEST(DataTypeSerDeParquetTest, MaterializesTimestampUnitsAndNegativeEpochDirectl EXPECT_EQ(type.to_string(*column, 2), "1970-01-01 00:00:01.000001"); } +TEST(DataTypeSerDeParquetTest, MaterializesTimestampNsExactlyFromPlainAndDictionaryValues) { + DataTypeTimeStampNs type; + const auto serde = type.get_serde(); + const ParquetDecodeContext plain_context {.physical_type = ParquetPhysicalType::INT64, + .logical_type = ParquetLogicalType::TIMESTAMP, + .time_unit = ParquetTimeUnit::NANOS, + .timestamp_is_adjusted_to_utc = false}; + { + TestParquetDecodeSource source; + source.set_fixed_values({std::numeric_limits::min(), -1, 0, 123456789, + std::numeric_limits::max()}); + ParquetMaterializationState state; + auto column = type.create_column(); + + ASSERT_TRUE(serde->read_column_from_parquet(*column, source, plain_context, 5, state).ok()); + const auto& data = assert_cast(*column).get_data(); + ASSERT_EQ(data.size(), 5); + EXPECT_EQ(data[0].epoch_nanos(), std::numeric_limits::min()); + EXPECT_EQ(data[1].epoch_nanos(), -1); + EXPECT_EQ(data[2].epoch_nanos(), 0); + EXPECT_EQ(data[3].epoch_nanos(), 123456789); + EXPECT_EQ(data[4].epoch_nanos(), std::numeric_limits::max()); + } + { + TestParquetDecodeSource source; + source.set_fixed_dictionary({-1, 0, 123456789}, {2, 0, 1, 2}); + auto dictionary_context = plain_context; + dictionary_context.encoding = ParquetValueEncoding::DICTIONARY; + ParquetMaterializationState state; + auto column = type.create_column(); + + ASSERT_TRUE(serde->read_column_from_parquet(*column, source, dictionary_context, 4, state) + .ok()); + const auto& data = assert_cast(*column).get_data(); + EXPECT_EQ(data[0].epoch_nanos(), 123456789); + EXPECT_EQ(data[1].epoch_nanos(), -1); + EXPECT_EQ(data[2].epoch_nanos(), 0); + EXPECT_EQ(data[3].epoch_nanos(), 123456789); + EXPECT_EQ(source.dictionary_decode_calls(), 1); + } +} + +TEST(DataTypeSerDeParquetTest, MaterializesTimestampNsInt96AndTimezoneExactly) { + DataTypeTimeStampNs type; + const auto serde = type.get_serde(); + { + TestParquetDecodeSource source; + source.set_fixed_values( + {{123456789, JULIAN_UNIX_EPOCH}, {NANOS_PER_DAY - 1, JULIAN_UNIX_EPOCH - 1}}); + ParquetDecodeContext context {.physical_type = ParquetPhysicalType::INT96, + .logical_type = ParquetLogicalType::TIMESTAMP}; + ParquetMaterializationState state; + auto column = type.create_column(); + + ASSERT_TRUE(serde->read_column_from_parquet(*column, source, context, 2, state).ok()); + const auto& data = assert_cast(*column).get_data(); + EXPECT_EQ(data[0].epoch_nanos(), 123456789); + EXPECT_EQ(data[1].epoch_nanos(), -1); + } + { + TimezoneUtils::load_timezones_to_cache(); + cctz::time_zone shanghai; + ASSERT_TRUE(TimezoneUtils::find_cctz_time_zone("Asia/Shanghai", shanghai)); + TestParquetDecodeSource source; + source.set_fixed_values({0, -1}); + ParquetDecodeContext context {.physical_type = ParquetPhysicalType::INT64, + .logical_type = ParquetLogicalType::TIMESTAMP, + .time_unit = ParquetTimeUnit::NANOS, + .timestamp_is_adjusted_to_utc = true, + .timezone = &shanghai}; + ParquetMaterializationState state; + auto column = type.create_column(); + + ASSERT_TRUE(serde->read_column_from_parquet(*column, source, context, 2, state).ok()); + EXPECT_EQ(type.to_string(*column, 0), "1970-01-01 08:00:00.000000000"); + EXPECT_EQ(type.to_string(*column, 1), "1970-01-01 07:59:59.999999999"); + } +} + +TEST(DataTypeSerDeParquetTest, TimestampNsConversionFailuresAndRawPredicateAreExact) { + DataTypeTimeStampNs type; + const auto serde = type.get_serde(); + const ParquetDecodeContext millis_context {.physical_type = ParquetPhysicalType::INT64, + .logical_type = ParquetLogicalType::TIMESTAMP, + .time_unit = ParquetTimeUnit::MILLIS, + .timestamp_is_adjusted_to_utc = false}; + { + TestParquetDecodeSource source; + source.set_fixed_values({std::numeric_limits::max(), 0}); + IColumn::Filter null_map(2, 0); + ParquetMaterializationState state; + state.conversion_failure_null_map = &null_map; + auto column = type.create_column(); + + ASSERT_TRUE( + serde->read_column_from_parquet(*column, source, millis_context, 2, state).ok()); + EXPECT_EQ(null_map, IColumn::Filter({1, 0})); + EXPECT_EQ(assert_cast(*column).get_data()[1].epoch_nanos(), 0); + } + { + TestParquetDecodeSource source; + source.set_fixed_values({std::numeric_limits::max()}); + ParquetMaterializationState state; + state.enable_strict_mode = true; + auto column = type.create_column(); + column->insert_default(); + + EXPECT_TRUE(serde->read_column_from_parquet(*column, source, millis_context, 1, state) + .is()); + EXPECT_EQ(column->size(), 1); + } + { + TestParquetDecodeSource source; + source.set_fixed_values({-1, 0, 123456789}); + auto nanos_context = millis_context; + nanos_context.time_unit = ParquetTimeUnit::NANOS; + CapturingLogicalValueConsumer consumer; + + ASSERT_TRUE(serde->supports_parquet_raw_predicate(nanos_context)); + ASSERT_TRUE( + serde->read_parquet_raw_predicate(source, nanos_context, 3, false, consumer).ok()); + const auto values = consumer.typed_values(); + ASSERT_EQ(values.size(), 3); + EXPECT_EQ(values[0].epoch_nanos(), -1); + EXPECT_EQ(values[1].epoch_nanos(), 0); + EXPECT_EQ(values[2].epoch_nanos(), 123456789); + EXPECT_EQ(consumer.nulls, IColumn::Filter(3, 0)); + } +} + TEST(DataTypeSerDeParquetTest, MaterializesTimeUnitsDirectly) { struct TimeUnitCase { ParquetTimeUnit unit; diff --git a/be/test/core/jsonb/convert_field_to_type_test.cpp b/be/test/core/jsonb/convert_field_to_type_test.cpp index 8c96894d3d1f34..4eef138c54a38c 100644 --- a/be/test/core/jsonb/convert_field_to_type_test.cpp +++ b/be/test/core/jsonb/convert_field_to_type_test.cpp @@ -86,6 +86,26 @@ TEST_F(ConvertFieldToTypeTest, FieldVisitorToJsonb_Int64) { ASSERT_EQ(doc->getValue()->int_val(), test_value); } +TEST_F(ConvertFieldToTypeTest, FieldVisitorToJsonb_TimeStampNs) { + JsonbWriter writer; + constexpr int64_t epoch_nanos = -1; + Field timestamp_ns_field = + Field::create_field(TimeStampNsValue(epoch_nanos)); + + dispatch([&writer](const auto& value) { FieldVisitorToJsonb()(value, &writer); }, + timestamp_ns_field); + + const auto* output = writer.getOutput(); + ASSERT_NE(output, nullptr); + const JsonbDocument* document = nullptr; + ASSERT_TRUE( + JsonbDocument::checkAndCreateDocument(output->getBuffer(), output->getSize(), &document) + .ok()); + ASSERT_NE(document, nullptr); + ASSERT_TRUE(document->getValue()->isInt64()); + EXPECT_EQ(document->getValue()->int_val(), epoch_nanos); +} + TEST_F(ConvertFieldToTypeTest, FieldVisitorToJsonb_UInt64) { JsonbWriter writer; diff --git a/be/test/exec/common/schema_util_test.cpp b/be/test/exec/common/schema_util_test.cpp index fe3dd4d6e7185b..22d983523cbc01 100644 --- a/be/test/exec/common/schema_util_test.cpp +++ b/be/test/exec/common/schema_util_test.cpp @@ -34,6 +34,7 @@ #include "core/data_type/data_type_nothing.h" #include "core/data_type/data_type_string.h" #include "core/data_type/data_type_time.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/data_type/data_type_variant.h" #include "core/data_type/data_type_variant_v2.h" #include "core/data_type_serde/data_type_jsonb_serde.h" @@ -1023,6 +1024,14 @@ TEST_F(SchemaUtilTest, TestGetColumnByTypeEdgeCases) { EXPECT_EQ(datetime_v2_column.precision(), -1); EXPECT_EQ(datetime_v2_column.frac(), 6); + auto timestamp_ns_type = std::make_shared(); + auto timestamp_ns_column = + variant_util::get_column_by_type(timestamp_ns_type, "timestamp_ns_col", ext_info); + EXPECT_EQ(timestamp_ns_column.type(), FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS); + EXPECT_EQ(timestamp_ns_column.length(), sizeof(TimeStampNsValue)); + EXPECT_TRUE(variant_util::is_bf_supported_by_fe_for_variant_subcolumn( + FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS)); + // Test invalid type auto invalid_type = std::make_shared(); EXPECT_THROW(variant_util::get_column_by_type(invalid_type, "invalid_col", ext_info), diff --git a/be/test/exec/operator/scan_normalize_predicate_test.cpp b/be/test/exec/operator/scan_normalize_predicate_test.cpp index d6fcd73d2be4ea..b0f71f2eea45fa 100644 --- a/be/test/exec/operator/scan_normalize_predicate_test.cpp +++ b/be/test/exec/operator/scan_normalize_predicate_test.cpp @@ -23,6 +23,7 @@ #include "core/column/column_const.h" #include "core/data_type/data_type_factory.hpp" #include "core/data_type/data_type_string.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/data_type/data_type_timestamptz.h" #include "core/data_type/define_primitive_type.h" #include "core/data_type/primitive_type.h" @@ -30,6 +31,7 @@ #include "exec/operator/mock_scan_operator.h" #include "exec/operator/operator_helper.h" #include "exprs/function/in.h" +#include "storage/olap_scan_common.h" #include "testutil/column_helper.h" #include "testutil/mock/mock_descriptors.h" #include "testutil/mock/mock_fn_call.h" @@ -1911,4 +1913,70 @@ TEST_F(ScanNormalizePredicate, test_timestamptz_predicate) { output_range); } } + +// NOLINTNEXTLINE(readability-function-cognitive-complexity) -- GTest assertions inflate it. +TEST_F(ScanNormalizePredicate, TimestampNsInPredicateBuildsPointScanKeys) { + constexpr int kSlotId = 0; + const std::vector values = { + TimeStampNsValue(std::numeric_limits::min()), TimeStampNsValue(-1), + TimeStampNsValue(0), TimeStampNsValue(1), + TimeStampNsValue(std::numeric_limits::max())}; + + SlotDescriptor slot_desc; + slot_desc._type = + DataTypeFactory::instance().create_data_type(PrimitiveType::TYPE_TIMESTAMP_NS, false); + auto local_state = std::make_shared(state.get(), op.get()); + local_state->_slot_id_to_value_range[kSlotId] = ColumnValueRange( + "dt", false, 0, TimeStampNsValue::FRACTIONAL_DIGITS); + local_state->_slot_id_to_predicates[kSlotId] = std::vector>(); + op->_slot_id_to_slot_desc[kSlotId] = &slot_desc; + + auto slot_ref = std::make_shared(kSlotId, std::make_shared()); + auto context = + MockInExpr::create_with_ctx(ColumnHelper::create_column(values)); + auto in_predicate = context->root(); + in_predicate->add_child(slot_ref); + in_predicate->_node_type = TExprNodeType::IN_PRED; + slot_ref->_slot_id = kSlotId; + context->_prepared = true; + context->_opened = true; + + VExprSPtr new_root; + EXPECT_TRUE(local_state->_normalize_predicate(context.get(), context->root(), new_root)); + EXPECT_EQ(new_root, nullptr); + ASSERT_EQ(local_state->_slot_id_to_predicates[kSlotId].size(), 1); + + auto* normalized_range = std::get_if>( + &local_state->_slot_id_to_value_range[kSlotId]); + ASSERT_NE(normalized_range, nullptr); + ASSERT_TRUE(normalized_range->is_fixed_value_range()); + ASSERT_EQ(normalized_range->get_fixed_value_size(), values.size()); + + OlapScanKeys scan_keys; + bool exact_value = true; + bool eos = false; + bool should_break = false; + EXPECT_TRUE(scan_keys.extend_scan_key(*normalized_range, 1024, &exact_value, + &eos, &should_break)); + EXPECT_TRUE(exact_value); + EXPECT_FALSE(eos); + EXPECT_FALSE(should_break); + EXPECT_FALSE(scan_keys.has_range_value()); + ASSERT_EQ(scan_keys.size(), values.size()); + + std::vector> key_ranges; + EXPECT_TRUE(scan_keys.get_key_range(&key_ranges)); + ASSERT_EQ(key_ranges.size(), values.size()); + for (size_t row = 0; row < values.size(); ++row) { + const auto& key_range = *key_ranges[row]; + EXPECT_TRUE(key_range.has_lower_bound); + EXPECT_TRUE(key_range.has_upper_bound); + EXPECT_TRUE(key_range.begin_include); + EXPECT_TRUE(key_range.end_include); + ASSERT_EQ(key_range.begin_scan_range.size(), 1); + ASSERT_EQ(key_range.end_scan_range.size(), 1); + EXPECT_EQ(key_range.begin_scan_range.get_field(0).get(), values[row]); + EXPECT_EQ(key_range.end_scan_range.get_field(0).get(), values[row]); + } +} } // namespace doris diff --git a/be/test/exec/runtime_filter/runtime_filter_partition_pruner_test.cpp b/be/test/exec/runtime_filter/runtime_filter_partition_pruner_test.cpp index 1c034a207cc61a..48976349ad6331 100644 --- a/be/test/exec/runtime_filter/runtime_filter_partition_pruner_test.cpp +++ b/be/test/exec/runtime_filter/runtime_filter_partition_pruner_test.cpp @@ -547,6 +547,8 @@ TEST_F(RuntimeFilterPartitionPrunerTest, ParseAndPrunePrimitiveTypeMatrix) { assert_parse_and_prune_type(date_v2(2024, 1, 1), date_v2(2024, 2, 1)); assert_parse_and_prune_type(datetime_v2(2024, 1, 1), datetime_v2(2024, 2, 1), 0, 6); + assert_parse_and_prune_type(TimeStampNsValue(-1), TimeStampNsValue(1), 0, + TimeStampNsValue::FRACTIONAL_DIGITS); assert_parse_and_prune_type(timestamptz(2024, 1, 1), timestamptz(2024, 2, 1), 0, 6); assert_parse_and_prune_type(Decimal32(100), Decimal32(200), 9, 2); diff --git a/be/test/exec/runtime_filter/runtime_filter_wrapper_test.cpp b/be/test/exec/runtime_filter/runtime_filter_wrapper_test.cpp index d5b2f9d9641276..c6c53eee39de28 100644 --- a/be/test/exec/runtime_filter/runtime_filter_wrapper_test.cpp +++ b/be/test/exec/runtime_filter/runtime_filter_wrapper_test.cpp @@ -230,6 +230,7 @@ TEST_F(RuntimeFilterWrapperTest, TestInAssign) { APPLY_FOR_PRIMITIVE_BASE_TYPE(TYPE_DOUBLE); APPLY_FOR_PRIMITIVE_BASE_TYPE(TYPE_DATEV2); APPLY_FOR_PRIMITIVE_BASE_TYPE(TYPE_DATETIMEV2); + APPLY_FOR_PRIMITIVE_BASE_TYPE(TYPE_TIMESTAMP_NS); APPLY_FOR_PRIMITIVE_TYPE(TYPE_DATETIME, VecDateTimeValue(0, 3, 0, 0, 0, 2020, 1, 1), VecDateTimeValue(0, 3, 0, 0, 0, 2020, 1, 2)); APPLY_FOR_PRIMITIVE_TYPE(TYPE_DATE, VecDateTimeValue(0, 2, 0, 0, 0, 2020, 1, 1), @@ -309,6 +310,7 @@ TEST_F(RuntimeFilterWrapperTest, TestMinMaxAssign) { APPLY_FOR_PRIMITIVE_BASE_TYPE(TYPE_DOUBLE); APPLY_FOR_PRIMITIVE_BASE_TYPE(TYPE_DATEV2); APPLY_FOR_PRIMITIVE_BASE_TYPE(TYPE_DATETIMEV2); + APPLY_FOR_PRIMITIVE_BASE_TYPE(TYPE_TIMESTAMP_NS); APPLY_FOR_PRIMITIVE_TYPE(TYPE_DATETIME, VecDateTimeValue(0, 3, 0, 0, 0, 2020, 1, 1), VecDateTimeValue(0, 3, 0, 0, 0, 2020, 1, 2)); APPLY_FOR_PRIMITIVE_TYPE(TYPE_DATE, VecDateTimeValue(0, 2, 0, 0, 0, 2020, 1, 1), diff --git a/be/test/exec/sink/tablet_sink_hash_partitioner_test.cpp b/be/test/exec/sink/tablet_sink_hash_partitioner_test.cpp index ba587b3c3ba89b..e1e4e7b7716f71 100644 --- a/be/test/exec/sink/tablet_sink_hash_partitioner_test.cpp +++ b/be/test/exec/sink/tablet_sink_hash_partitioner_test.cpp @@ -36,6 +36,7 @@ #include "common/config.h" #include "core/assert_cast.h" #include "core/column/column_vector.h" +#include "core/data_type/data_type_date_or_datetime_v2.h" #include "core/data_type/data_type_nullable.h" #include "core/data_type/data_type_number.h" #include "exec/operator/exchange_sink_operator.h" @@ -59,6 +60,69 @@ using doris::ExchangeSinkLocalState; using doris::ExchangeSinkOperatorX; using doris::OperatorContext; +TExprNode _make_timestamp_ns_literal(std::string value) { + TExprNode node; + node.__set_node_type(TExprNodeType::DATE_LITERAL); + node.__set_num_children(0); + + TDateLiteral literal; + literal.__set_value(std::move(value)); + node.__set_date_literal(literal); + + TTypeDesc type_desc = create_type_desc(PrimitiveType::TYPE_TIMESTAMP_NS); + type_desc.__set_is_nullable(false); + node.__set_type(type_desc); + node.__set_is_nullable(false); + return node; +} + +void _build_timestamp_ns_schema(OperatorContext& ctx, TOlapTableSchemaParam& tschema, + int64_t& schema_index_id) { + TTypeDesc type_desc = create_type_desc(PrimitiveType::TYPE_TIMESTAMP_NS); + + TDescriptorTableBuilder dtb; + TTupleDescriptorBuilder tuple_builder; + tuple_builder.add_slot(TSlotDescriptorBuilder() + .set_slotType(type_desc) + .nullable(true) + .column_name("dt") + .column_pos(0) + .build()); + tuple_builder.build(&dtb); + + auto thrift_desc_tbl = dtb.desc_tbl(); + DescriptorTbl* desc_tbl = nullptr; + auto st = DescriptorTbl::create(ctx.state.obj_pool(), thrift_desc_tbl, &desc_tbl); + ASSERT_TRUE(st.ok()) << st.to_string(); + ctx.state.set_desc_tbl(desc_tbl); + + tschema.db_id = 1; + tschema.table_id = 2; + tschema.version = 0; + tschema.slot_descs = thrift_desc_tbl.slotDescriptors; + tschema.tuple_desc = thrift_desc_tbl.tupleDescriptors.front(); + + TOlapTableIndexSchema index_schema; + index_schema.id = 10; + index_schema.columns = {"dt"}; + index_schema.schema_hash = 123; + tschema.indexes = {index_schema}; + schema_index_id = index_schema.id; +} + +TOlapTablePartition _make_timestamp_ns_partition(int64_t id, int64_t schema_index_id) { + TOlapTablePartition partition; + partition.id = id; + partition.num_buckets = 1; + partition.__set_is_mutable(true); + + TOlapTableIndexTablets index_tablets; + index_tablets.index_id = schema_index_id; + index_tablets.tablets = {id * 100}; + partition.indexes = {index_tablets}; + return partition; +} + std::shared_ptr _create_parent_operator( OperatorContext& ctx, const std::shared_ptr& row_desc_holder) { TDataStreamSink sink; @@ -275,5 +339,50 @@ TEST(TabletSinkHashPartitionerTest, OlapTabletFinderRoundRobinEveryBatch) { EXPECT_EQ(tablet_index[0], 0); } } + +TEST(TabletSinkHashPartitionerTest, TimeStampNsRangePartitionKey) { + OperatorContext ctx; + + TOlapTableSchemaParam tschema; + int64_t schema_index_id = 0; + _build_timestamp_ns_schema(ctx, tschema, schema_index_id); + + auto schema = std::make_shared(); + auto st = schema->init(tschema); + ASSERT_TRUE(st.ok()) << st.to_string(); + + TOlapTablePartitionParam partition_param; + partition_param.db_id = 1; + partition_param.table_id = 2; + partition_param.version = 0; + partition_param.__set_partition_type(TPartitionType::RANGE_PARTITIONED); + partition_param.__set_partition_columns({"dt"}); + + auto before_epoch = _make_timestamp_ns_partition(1, schema_index_id); + before_epoch.__set_end_keys({_make_timestamp_ns_literal("1970-01-01 00:00:00")}); + + auto epoch = _make_timestamp_ns_partition(2, schema_index_id); + epoch.__set_start_keys({_make_timestamp_ns_literal("1970-01-01 00:00:00")}); + epoch.__set_end_keys({_make_timestamp_ns_literal("1970-01-01 00:00:00.000000002")}); + + auto after_epoch = _make_timestamp_ns_partition(3, schema_index_id); + after_epoch.__set_start_keys({_make_timestamp_ns_literal("1970-01-01 00:00:00.000000002")}); + partition_param.partitions = {epoch, before_epoch, after_epoch}; + + VOlapTablePartitionParam partitions(schema, partition_param); + st = partitions.init(); + ASSERT_TRUE(st.ok()) << st.to_string(); + + auto* slot = schema->tuple_desc()->slots().front(); + auto column = slot->get_empty_mutable_column(); + const TimeStampNsValue min_value(std::numeric_limits::min()); + column->insert_data(reinterpret_cast(&min_value), 0); + Block block({{std::move(column), slot->get_data_type_ptr(), slot->col_name()}}); + + VOlapTablePartition* result = nullptr; + EXPECT_TRUE(partitions.find_partition(&block, 0, result)); + ASSERT_NE(result, nullptr); + EXPECT_EQ(result->id, before_epoch.id); +} } // anonymous namespace } // namespace doris diff --git a/be/test/exec/sink/writer/iceberg/partition_transformers_test.cpp b/be/test/exec/sink/writer/iceberg/partition_transformers_test.cpp index 974eb817e8872a..34d9a25804579a 100644 --- a/be/test/exec/sink/writer/iceberg/partition_transformers_test.cpp +++ b/be/test/exec/sink/writer/iceberg/partition_transformers_test.cpp @@ -22,6 +22,7 @@ #include #include "core/data_type/data_type_date_or_datetime_v2.h" +#include "core/data_type/data_type_timestamp_ns.h" namespace doris { @@ -462,6 +463,38 @@ TEST_F(PartitionTransformersTest, test_timestamp_hour_transform) { } } +TEST_F(PartitionTransformersTest, test_timestamp_ns_transforms) { + DateV2Value datetime; + datetime.unchecked_set_time(2017, 11, 16, 22, 31, 8, 123456); + TimeStampNsValue value; + ASSERT_TRUE(value.from_datetime(datetime, 789)); + + auto column = ColumnTimeStampNs::create(); + column->get_data().push_back(value); + auto source_type = std::make_shared(); + Block block({ColumnWithTypeAndName(column->get_ptr(), source_type, "test_timestamp_ns")}); + + TimestampBucketPartitionColumnTransform bucket(source_type, 16); + auto bucket_result = bucket.apply(block, 0); + const auto& bucket_data = + assert_cast(bucket_result.column.get())->get_data(); + uint32_t expected_hash = HashUtil::murmur_hash3_32(&value, sizeof(value), 0); + EXPECT_EQ((expected_hash & INT32_MAX) % 16, bucket_data[0]); + + TimestampYearPartitionColumnTransform year(source_type); + EXPECT_EQ(47, + assert_cast(year.apply(block, 0).column.get())->get_data()[0]); + TimestampMonthPartitionColumnTransform month(source_type); + EXPECT_EQ(574, + assert_cast(month.apply(block, 0).column.get())->get_data()[0]); + TimestampDayPartitionColumnTransform day(source_type); + EXPECT_EQ(17486, + assert_cast(day.apply(block, 0).column.get())->get_data()[0]); + TimestampHourPartitionColumnTransform hour(source_type); + EXPECT_EQ(419686, + assert_cast(hour.apply(block, 0).column.get())->get_data()[0]); +} + TEST_F(PartitionTransformersTest, test_void_transform) { const std::vector values({1, -1}); auto column = ColumnInt32::create(); diff --git a/be/test/exprs/aggregate/agg_approx_count_distinct_test.cpp b/be/test/exprs/aggregate/agg_approx_count_distinct_test.cpp new file mode 100644 index 00000000000000..1f8c3f4310fbc9 --- /dev/null +++ b/be/test/exprs/aggregate/agg_approx_count_distinct_test.cpp @@ -0,0 +1,64 @@ +// 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 + +#include +#include +#include + +#include "core/column/column_vector.h" +#include "core/data_type/data_type_timestamp_ns.h" +#include "exprs/aggregate/aggregate_function.h" +#include "exprs/aggregate/aggregate_function_simple_factory.h" + +namespace doris { + +void register_aggregate_function_approx_count_distinct(AggregateFunctionSimpleFactory& factory); + +TEST(AggApproxCountDistinctTest, TimeStampNs) { + AggregateFunctionSimpleFactory factory; + register_aggregate_function_approx_count_distinct(factory); + + auto data_type = std::make_shared(); + const DataTypes argument_types = {data_type}; + for (const std::string function_name : {"approx_count_distinct", "ndv"}) { + auto function = factory.get(function_name, argument_types, nullptr, false, -1); + ASSERT_NE(function, nullptr); + + auto column = ColumnTimeStampNs::create(); + for (const int64_t epoch_nanos : {-1, 0, 1, 1, 1'000'000'001}) { + column->insert_value(TimeStampNsValue(epoch_nanos)); + } + + std::unique_ptr memory(new char[function->size_of_data()]); + AggregateDataPtr place = memory.get(); + function->create(place); + Arena arena; + const IColumn* columns[] = {column.get()}; + for (size_t row = 0; row < column->size(); ++row) { + function->add(place, columns, row, arena); + } + + auto result = ColumnInt64::create(); + function->insert_result_into(place, *result); + EXPECT_EQ(result->get_element(0), 4); + function->destroy(place); + } +} + +} // namespace doris diff --git a/be/test/exprs/aggregate/agg_min_max_test.cpp b/be/test/exprs/aggregate/agg_min_max_test.cpp index 3f2080fc8304e6..86b19d7462bad8 100644 --- a/be/test/exprs/aggregate/agg_min_max_test.cpp +++ b/be/test/exprs/aggregate/agg_min_max_test.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -34,6 +35,7 @@ #include "core/data_type/data_type_nullable.h" #include "core/data_type/data_type_number.h" #include "core/data_type/data_type_string.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/field.h" #include "core/string_ref.h" #include "core/types.h" @@ -135,6 +137,41 @@ TEST_P(AggMinMaxTest, min_max_decimal_test) { } } +TEST_P(AggMinMaxTest, min_max_timestamp_ns_test) { + Arena arena; + const std::string min_max_type = GetParam(); + const std::vector epoch_nanos = {0, -1, std::numeric_limits::max(), + std::numeric_limits::min(), 1}; + + auto data_type = std::make_shared(); + auto column = ColumnTimeStampNs::create(); + for (const int64_t value : epoch_nanos) { + column->insert_value(TimeStampNsValue(value)); + } + + AggregateFunctionSimpleFactory factory; + register_aggregate_function_minmax(factory); + DataTypes data_types = {data_type}; + auto agg_function = factory.get(min_max_type, data_types, data_type, false, -1); + ASSERT_NE(agg_function, nullptr); + + std::unique_ptr memory(new char[agg_function->size_of_data()]); + AggregateDataPtr place = memory.get(); + agg_function->create(place); + + const IColumn* columns[1] = {column.get()}; + for (size_t row = 0; row < epoch_nanos.size(); ++row) { + agg_function->add(place, columns, row, arena); + } + + auto result = ColumnTimeStampNs::create(); + agg_function->insert_result_into(place, *result); + const int64_t expected = min_max_type == "min" ? std::numeric_limits::min() + : std::numeric_limits::max(); + EXPECT_EQ(result->get_element(0).epoch_nanos(), expected); + agg_function->destroy(place); +} + TEST_P(AggMinMaxTest, min_max_string_test) { Arena arena; std::string min_max_type = GetParam(); diff --git a/be/test/exprs/aggregate/vec_sequence_match_test.cpp b/be/test/exprs/aggregate/vec_sequence_match_test.cpp index 3518a3e06bbfe0..b9f440978368c9 100644 --- a/be/test/exprs/aggregate/vec_sequence_match_test.cpp +++ b/be/test/exprs/aggregate/vec_sequence_match_test.cpp @@ -26,6 +26,7 @@ #include "core/data_type/data_type_date_or_datetime_v2.h" #include "core/data_type/data_type_number.h" #include "core/data_type/data_type_string.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/string_buffer.hpp" #include "core/types.h" #include "core/value/vdatetime_value.h" @@ -99,6 +100,15 @@ class VSequenceMatchTest : public testing::Test { Arena arena; }; +TEST(VSequenceMatchTimeStampNsTest, FactoryCreatesBothFunctions) { + AggregateFunctionSimpleFactory factory = AggregateFunctionSimpleFactory::instance(); + DataTypes data_types = {std::make_shared(), + std::make_shared(), + std::make_shared(), std::make_shared()}; + EXPECT_NE(factory.get("sequence_match", data_types, nullptr, false, -1), nullptr); + EXPECT_NE(factory.get("sequence_count", data_types, nullptr, false, -1), nullptr); +} + TEST_F(VSequenceMatchTest, testMatchEmpty) { std::unique_ptr memory(new char[agg_function_sequence_match->size_of_data()]); AggregateDataPtr place = memory.get(); diff --git a/be/test/exprs/aggregate/vec_window_funnel_test.cpp b/be/test/exprs/aggregate/vec_window_funnel_test.cpp index 01ad0b050f2739..ed87928eec260c 100644 --- a/be/test/exprs/aggregate/vec_window_funnel_test.cpp +++ b/be/test/exprs/aggregate/vec_window_funnel_test.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -28,10 +29,12 @@ #include "core/data_type/data_type_date_or_datetime_v2.h" #include "core/data_type/data_type_number.h" #include "core/data_type/data_type_string.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/string_buffer.hpp" #include "core/value/vdatetime_value.h" #include "exprs/aggregate/aggregate_function.h" #include "exprs/aggregate/aggregate_function_simple_factory.h" +#include "exprs/aggregate/aggregate_function_window_funnel.h" #include "gtest/gtest_pred_impl.h" namespace doris { @@ -65,6 +68,53 @@ class VWindowFunnelTest : public testing::Test { Arena arena; }; +TEST(VWindowFunnelTimeStampNsTest, FactoryCreatesFunction) { + AggregateFunctionSimpleFactory factory = AggregateFunctionSimpleFactory::instance(); + DataTypes data_types = {std::make_shared(), std::make_shared(), + std::make_shared(), + std::make_shared(), std::make_shared()}; + EXPECT_NE(factory.get("window_funnel", data_types, nullptr, false, + BeExecVersionManager::get_newest_version()), + nullptr); +} + +TEST(VWindowFunnelTimeStampNsTest, HandlesUpperBoundaryWindow) { + WindowFunnelState state(2); + state.enable_mode = true; + state.window = 1; + state.window_funnel_mode = WindowFunnelMode::DEFAULT; + state.events_list.dt.emplace_back(std::numeric_limits::max() - 500000000); + state.events_list.dt.emplace_back(std::numeric_limits::max()); + state.events_list.event_columns_data[0].emplace_back(1); + state.events_list.event_columns_data[0].emplace_back(0); + state.events_list.event_columns_data[1].emplace_back(0); + state.events_list.event_columns_data[1].emplace_back(1); + + EXPECT_EQ(2, state.get()); +} + +TEST(VWindowFunnelTimeStampNsTest, PreservesNegativeTimestampDuringSerialization) { + WindowFunnelState source(1); + source.enable_mode = true; + source.window = 1; + source.window_funnel_mode = WindowFunnelMode::DEFAULT; + source.events_list.dt.emplace_back(-1); + source.events_list.event_columns_data[0].emplace_back(1); + + ColumnString buffer; + VectorBufferWriter writer(buffer); + source.write(writer); + writer.commit(); + + WindowFunnelState restored(1); + restored.enable_mode = true; + VectorBufferReader reader(buffer.get_data_at(0)); + restored.read(reader); + + ASSERT_EQ(1, restored.events_list.dt.size()); + EXPECT_EQ(-1, restored.events_list.dt[0].epoch_nanos()); +} + TEST_F(VWindowFunnelTest, testEmpty) { std::unique_ptr memory(new char[agg_function->size_of_data()]); AggregateDataPtr place = memory.get(); diff --git a/be/test/exprs/aggregate/vec_window_funnel_v2_test.cpp b/be/test/exprs/aggregate/vec_window_funnel_v2_test.cpp index cbf6d0f9bf85c2..9b907d153d1755 100644 --- a/be/test/exprs/aggregate/vec_window_funnel_v2_test.cpp +++ b/be/test/exprs/aggregate/vec_window_funnel_v2_test.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -28,10 +29,12 @@ #include "core/data_type/data_type_date_or_datetime_v2.h" #include "core/data_type/data_type_number.h" #include "core/data_type/data_type_string.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/string_buffer.hpp" #include "core/value/vdatetime_value.h" #include "exprs/aggregate/aggregate_function.h" #include "exprs/aggregate/aggregate_function_simple_factory.h" +#include "exprs/aggregate/aggregate_function_window_funnel_v2.h" #include "gtest/gtest_pred_impl.h" namespace doris { @@ -65,6 +68,26 @@ class VWindowFunnelV2Test : public testing::Test { Arena arena; }; +TEST(VWindowFunnelV2TimeStampNsTest, FactoryCreatesFunction) { + AggregateFunctionSimpleFactory factory = AggregateFunctionSimpleFactory::instance(); + DataTypes data_types = {std::make_shared(), std::make_shared(), + std::make_shared(), + std::make_shared(), std::make_shared()}; + EXPECT_NE(factory.get("window_funnel_v2", data_types, nullptr, false, + BeExecVersionManager::get_newest_version()), + nullptr); +} + +TEST(VWindowFunnelV2TimeStampNsTest, HandlesUpperBoundaryWindow) { + WindowFunnelStateV2 state(2); + state.window = 1; + state.window_funnel_mode = WindowFunnelMode::DEFAULT; + state.events_list.push_back({std::numeric_limits::max() - 500000000, 1}); + state.events_list.push_back({std::numeric_limits::max(), 2}); + + EXPECT_EQ(2, state.get()); +} + TEST_F(VWindowFunnelV2Test, testEmpty) { std::unique_ptr memory(new char[agg_function->size_of_data()]); AggregateDataPtr place = memory.get(); diff --git a/be/test/exprs/function/cast/cast_test.h b/be/test/exprs/function/cast/cast_test.h index e77b6f67aadb9c..c10a59305d7c06 100644 --- a/be/test/exprs/function/cast/cast_test.h +++ b/be/test/exprs/function/cast/cast_test.h @@ -163,6 +163,8 @@ struct FunctionCastTest : public testing::Test { return "datev2"; case TYPE_DATETIMEV2: /* 26 */ return precision > 0 ? fmt::format("datetimev2{}", precision) : "datetimev2"; + case TYPE_TIMESTAMP_NS: + return "timestamp_ns"; case TYPE_TIMEV2: /* 27 */ return "time"; case TYPE_DECIMAL32: /* 28 */ diff --git a/be/test/exprs/function/cast/cast_timestamp_ns_test.cpp b/be/test/exprs/function/cast/cast_timestamp_ns_test.cpp new file mode 100644 index 00000000000000..154e40685795ff --- /dev/null +++ b/be/test/exprs/function/cast/cast_timestamp_ns_test.cpp @@ -0,0 +1,241 @@ +// 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 "core/data_type/data_type_timestamp_ns.h" +#include "exprs/function/cast/cast_test.h" + +namespace doris { +using namespace ut_type; + +TEST_F(FunctionCastTest, string_to_timestamp_ns) { + const InputTypeSet input_types = {PrimitiveType::TYPE_VARCHAR}; + const DataSet data_set = { + {{std::string("1677-09-21 00:12:43.145224192")}, + std::string("1677-09-21 00:12:43.145224192")}, + {{std::string("1969-12-31 23:59:59.999999999")}, + std::string("1969-12-31 23:59:59.999999999")}, + {{std::string("1970-01-01 00:00:00.000000000")}, + std::string("1970-01-01 00:00:00.000000000")}, + {{std::string("2024-02-29 12:34:56.1234567894")}, + std::string("2024-02-29 12:34:56.123456789")}, + {{std::string("2024-02-29 12:34:56.1234567895")}, + std::string("2024-02-29 12:34:56.123456790")}, + {{std::string("2024-02-29 12:34:56.9999999995")}, + std::string("2024-02-29 12:34:57.000000000")}, + {{std::string("2024-02-29 12:34:56.123456789+08:00")}, + std::string("2024-02-29 12:34:56.123456789")}, + {{std::string("2262-04-11 23:47:16.854775807")}, + std::string("2262-04-11 23:47:16.854775807")}, + {{std::string("1677-09-21 00:12:43.145224191")}, Null()}, + {{std::string("2262-04-11 23:47:16.8547758075")}, Null()}, + {{std::string("2024-01-01 00:00:00.123.456")}, Null()}, + {{Null()}, Null()}, + }; + check_function_for_cast(input_types, data_set); +} + +TEST_F(FunctionCastTest, numeric_to_timestamp_ns) { + { + const InputTypeSet input_types = {PrimitiveType::TYPE_BIGINT}; + const DataSet data_set = { + {{int64_t(16770921001243)}, Null()}, + {{int64_t(19691231235959)}, std::string("1969-12-31 23:59:59.000000000")}, + {{int64_t(19700101000000)}, std::string("1970-01-01 00:00:00.000000000")}, + {{int64_t(22620411234716)}, std::string("2262-04-11 23:47:16.000000000")}, + {{int64_t(22620412000000)}, Null()}, + }; + check_function_for_cast(input_types, data_set); + } + { + const InputTypeSet input_types = {PrimitiveType::TYPE_DOUBLE}; + const DataSet data_set = { + {{double(19700101000000.125)}, std::string("1970-01-01 00:00:00.125000000")}, + {{double(20240229123456.5)}, std::string("2024-02-29 12:34:56.500000000")}, + {{double(22620412000000.0)}, Null()}, + }; + check_function_for_cast(input_types, data_set); + } + { + const InputTypeSet input_types = {{PrimitiveType::TYPE_DECIMAL128I, 10, 24}}; + const DataSet data_set = { + {{DECIMAL128V3(16770921001243, 1452241914, 10)}, Null()}, + {{DECIMAL128V3(16770921001243, 1452241915, 10)}, + std::string("1677-09-21 00:12:43.145224192")}, + {{DECIMAL128V3(19700101000000, 1234567895, 10)}, + std::string("1970-01-01 00:00:00.123456790")}, + {{DECIMAL128V3(19700101000000, 9999999995, 10)}, + std::string("1970-01-01 00:00:01.000000000")}, + {{DECIMAL128V3(22620411234716, 8547758074, 10)}, + std::string("2262-04-11 23:47:16.854775807")}, + {{DECIMAL128V3(22620411234716, 8547758075, 10)}, Null()}, + }; + check_function_for_cast(input_types, data_set); + } +} + +TEST_F(FunctionCastTest, datelike_to_timestamp_ns) { + { + const InputTypeSet input_types = {{PrimitiveType::TYPE_DATE}}; + const DataSet data_set = { + {{std::string("1677-09-21")}, Null()}, + {{std::string("1970-01-01")}, std::string("1970-01-01 00:00:00.000000000")}, + {{std::string("2262-04-11")}, std::string("2262-04-11 00:00:00.000000000")}, + }; + check_function_for_cast(input_types, data_set); + } + { + const InputTypeSet input_types = {{PrimitiveType::TYPE_DATEV2}}; + const DataSet data_set = { + {{std::string("1677-09-21")}, Null()}, + {{std::string("1677-09-22")}, std::string("1677-09-22 00:00:00.000000000")}, + {{std::string("1970-01-01")}, std::string("1970-01-01 00:00:00.000000000")}, + {{std::string("2262-04-11")}, std::string("2262-04-11 00:00:00.000000000")}, + {{std::string("2262-04-12")}, Null()}, + }; + check_function_for_cast(input_types, data_set); + } + { + const InputTypeSet input_types = {{PrimitiveType::TYPE_DATETIME}}; + const DataSet data_set = { + {{std::string("1677-09-21 00:12:43")}, Null()}, + {{std::string("1970-01-01 00:00:00")}, + std::string("1970-01-01 00:00:00.000000000")}, + {{std::string("2262-04-11 23:47:16")}, + std::string("2262-04-11 23:47:16.000000000")}, + }; + check_function_for_cast(input_types, data_set); + } + { + const InputTypeSet input_types = {{PrimitiveType::TYPE_DATETIMEV2, 6}}; + const DataSet data_set = { + {{std::string("1677-09-21 00:12:43.145224")}, Null()}, + {{std::string("1677-09-21 00:12:43.145225")}, + std::string("1677-09-21 00:12:43.145225000")}, + {{std::string("1970-01-01 00:00:00.000000")}, + std::string("1970-01-01 00:00:00.000000000")}, + {{std::string("2262-04-11 23:47:16.854775")}, + std::string("2262-04-11 23:47:16.854775000")}, + {{std::string("2262-04-11 23:47:16.854776")}, Null()}, + }; + check_function_for_cast(input_types, data_set); + } + { + const InputTypeSet input_types = {{PrimitiveType::TYPE_TIMEV2, 6}}; + const DataSet data_set = { + {{std::string("23:59:59.999999")}, std::string("2019-08-06 23:59:59.999999000")}, + {{std::string("-128:00:00")}, std::string("2019-07-31 16:00:00.000000000")}, + }; + check_function_for_cast(input_types, data_set); + } +} + +TEST_F(FunctionCastTest, datetimev2_to_timestamp_ns_strict_overflow) { + const InputTypeSet input_types = {{PrimitiveType::TYPE_DATETIMEV2, 6}}; + const DataSet valid_data_set = { + {{std::string("1677-09-21 00:12:43.145225")}, + std::string("1677-09-21 00:12:43.145225000")}, + {{std::string("1970-01-01 00:00:00.000000")}, + std::string("1970-01-01 00:00:00.000000000")}, + {{std::string("2262-04-11 23:47:16.854775")}, + std::string("2262-04-11 23:47:16.854775000")}, + }; + check_function_for_cast_strict_mode(input_types, valid_data_set); + + const DataSet overflow_data_set = { + {{std::string("1677-09-21 00:12:43.145224")}, Null()}, + {{std::string("2262-04-11 23:47:16.854776")}, Null()}, + }; + check_function_for_cast_strict_mode(input_types, overflow_data_set, + "TIMESTAMP_NS overflow"); +} + +TEST_F(FunctionCastTest, numeric_to_timestamp_ns_strict_overflow) { + const InputTypeSet input_types = {PrimitiveType::TYPE_BIGINT}; + const DataSet valid_data_set = { + {{int64_t(19700101000000)}, std::string("1970-01-01 00:00:00.000000000")}, + {{int64_t(22620411234716)}, std::string("2262-04-11 23:47:16.000000000")}, + }; + check_function_for_cast_strict_mode(input_types, valid_data_set); + + const DataSet overflow_data_set = { + {{int64_t(16770921001243)}, Null()}, + {{int64_t(22620412000000)}, Null()}, + }; + check_function_for_cast_strict_mode( + input_types, overflow_data_set, "outside the signed epoch-nanosecond range"); +} + +TEST_F(FunctionCastTest, timestamp_ns_to_supported_scalar_types) { + const InputTypeSet input_types = {{PrimitiveType::TYPE_TIMESTAMP_NS}}; + const DataSet datetime_data = { + {{std::string("1677-09-21 00:12:43.145224192")}, + std::string("1677-09-21 00:12:43.145224")}, + {{std::string("1969-12-31 23:59:59.999999999")}, + std::string("1970-01-01 00:00:00.000000")}, + {{std::string("2024-02-29 12:34:56.123456789")}, + std::string("2024-02-29 12:34:56.123457")}, + {{std::string("2262-04-11 23:47:16.854775807")}, + std::string("2262-04-11 23:47:16.854776")}, + }; + check_function_for_cast(input_types, datetime_data, 6); + check_function_for_cast(input_types, datetime_data, 6); + + const DataSet date_data = { + {{std::string("1677-09-21 00:12:43.145224192")}, std::string("1677-09-21")}, + {{std::string("1970-01-01 00:00:00.000000000")}, std::string("1970-01-01")}, + {{std::string("2262-04-11 23:47:16.854775807")}, std::string("2262-04-11")}, + }; + check_function_for_cast(input_types, date_data); + check_function_for_cast(input_types, date_data); + + const DataSet legacy_datetime_data = { + {{std::string("1677-09-21 00:12:43.145224192")}, std::string("1677-09-21 00:12:43")}, + {{std::string("1970-01-01 00:00:00.000000000")}, std::string("1970-01-01 00:00:00")}, + {{std::string("2262-04-11 23:47:16.854775807")}, std::string("2262-04-11 23:47:16")}, + }; + check_function_for_cast(input_types, legacy_datetime_data); + + const DataSet time_data = { + {{std::string("1677-09-21 00:12:43.145224192")}, std::string("00:12:43.145224")}, + {{std::string("1969-12-31 23:59:59.999999999")}, std::string("24:00:00.000000")}, + {{std::string("2024-02-29 12:34:56.123456789")}, std::string("12:34:56.123457")}, + }; + check_function_for_cast(input_types, time_data, 6); + + const DataSet integer_data = { + {{std::string("1677-09-21 00:12:43.145224192")}, int64_t(16770921001243)}, + {{std::string("1970-01-01 00:00:00.000000000")}, int64_t(19700101000000)}, + {{std::string("2262-04-11 23:47:16.854775807")}, int64_t(22620411234716)}, + }; + check_function_for_cast(input_types, integer_data); + check_function_for_cast( + input_types, + {{{std::string("1970-01-01 00:00:00.000000000")}, int128_t(19700101000000)}}); + check_function_for_cast( + input_types, + {{{std::string("1970-01-01 00:00:00.000000000")}, double(19700101000000)}}); +} + +TEST_F(FunctionCastTest, unsupported_timestamp_ns_cast) { + const InputTypeSet input_types = {{PrimitiveType::TYPE_TIMESTAMP_NS}}; + const DataSet data_set = { + {{std::string("2024-02-29 12:34:56.123456789")}, int32_t(0)}, + }; + check_function_for_cast(input_types, data_set, -1, -1, true, true); +} + +} // namespace doris diff --git a/be/test/exprs/function/cast/cast_to_timestamptz_test.cpp b/be/test/exprs/function/cast/cast_to_timestamptz_test.cpp index d704d25d358ad4..da140c14537476 100644 --- a/be/test/exprs/function/cast/cast_to_timestamptz_test.cpp +++ b/be/test/exprs/function/cast/cast_to_timestamptz_test.cpp @@ -22,12 +22,15 @@ #include "core/column/column_nullable.h" #include "core/data_type/data_type_date_or_datetime_v2.h" #include "core/data_type/data_type_string.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/data_type/data_type_timestamptz.h" #include "core/data_type/primitive_type.h" #include "core/value/timestamptz_value.h" #include "exprs/function/cast/cast_base.h" #include "exprs/function/cast/cast_test.h" #include "exprs/function/cast/cast_to_date.h" +#include "exprs/function/cast/cast_to_timestamp_ns.h" +#include "exprs/function/cast/cast_wrapper_decls.h" #include "testutil/column_helper.h" #include "testutil/datetime_ut_util.h" #include "testutil/mock/mock_runtime_state.h" @@ -263,6 +266,102 @@ TEST_F(CastTimeStampTzTest, from_datetime_non_strict_mode_to_timestamptz) { } } +TEST_F(CastTimeStampTzTest, timestamp_ns_and_timestamptz_round_trip) { + const auto make_timestamp_ns = [](std::string_view text) { + int64_t epoch_nanos = 0; + EXPECT_TRUE(parse_timestamp_ns(StringRef {text.data(), text.size()}, &epoch_nanos).ok()); + return TimeStampNsValue(epoch_nanos); + }; + + auto timestamp_ns_block = ColumnHelper::create_block( + {make_timestamp_ns("1677-09-21 00:12:43.145224192"), + make_timestamp_ns("1969-12-31 23:59:59.999999499"), + make_timestamp_ns("1969-12-31 23:59:59.999999500"), + make_timestamp_ns("2024-06-20 12:12:12.123456789"), + make_timestamp_ns("2262-04-11 23:47:16.854775807")}); + timestamp_ns_block.insert( + ColumnWithTypeAndName {nullptr, std::make_shared(6), "result"}); + + auto to_timestamptz = CastWrapper::create_timestamptz_wrapper( + &context, timestamp_ns_block.get_by_position(0).type); + auto status = to_timestamptz(&context, timestamp_ns_block, arguments, result, + timestamp_ns_block.rows(), nullptr); + ASSERT_TRUE(status.ok()) << status.to_string(); + const auto& nullable_timestamptz = + assert_cast(*timestamp_ns_block.get_by_position(result).column); + const auto& timestamptz_column = + assert_cast(nullable_timestamptz.get_nested_column()); + for (size_t i = 0; i < timestamp_ns_block.rows(); ++i) { + EXPECT_FALSE(nullable_timestamptz.is_null_at(i)); + } + EXPECT_EQ(TimestampTzValue {timestamptz_column.get_element(0)}.to_string(time_zone), + "1677-09-21 00:12:43.145224+08:00"); + EXPECT_EQ(TimestampTzValue {timestamptz_column.get_element(1)}.to_string(time_zone), + "1969-12-31 23:59:59.999999+08:00"); + EXPECT_EQ(TimestampTzValue {timestamptz_column.get_element(2)}.to_string(time_zone), + "1970-01-01 00:00:00.000000+08:00"); + EXPECT_EQ(TimestampTzValue {timestamptz_column.get_element(3)}.to_string(time_zone), + "2024-06-20 12:12:12.123457+08:00"); + EXPECT_EQ(TimestampTzValue {timestamptz_column.get_element(4)}.to_string(time_zone), + "2262-04-11 23:47:16.854776+08:00"); + + CastToImpl to_timestamp_ns; + auto timestamptz_block = ColumnHelper::create_block( + {make_timestamptz(2024, 6, 20, 4, 12, 12, 123456), + make_timestamptz(1969, 12, 31, 15, 59, 59, 999999)}); + timestamptz_block.get_by_position(0).type = std::make_shared(6); + timestamptz_block.insert( + ColumnWithTypeAndName {nullptr, std::make_shared(), "result"}); + + status = to_timestamp_ns.execute_impl(&context, timestamptz_block, arguments, result, + timestamptz_block.rows()); + ASSERT_TRUE(status.ok()) << status.to_string(); + const auto& timestamp_ns_column = assert_cast( + *timestamptz_block.get_by_position(result).column); + EXPECT_EQ(timestamp_ns_column.get_element(0).to_string(), "2024-06-20 12:12:12.123456000"); + EXPECT_EQ(timestamp_ns_column.get_element(1).to_string(), "1969-12-31 23:59:59.999999000"); +} + +TEST_F(CastTimeStampTzTest, timestamptz_to_timestamp_ns_range_overflow) { + const auto create_source_block = [] { + auto block = ColumnHelper::create_block( + {make_timestamptz(1677, 9, 20, 16, 12, 43, 145224), + make_timestamptz(1677, 9, 20, 16, 12, 43, 145225), + make_timestamptz(2262, 4, 11, 15, 47, 16, 854775), + make_timestamptz(2262, 4, 11, 15, 47, 16, 854776)}); + block.get_by_position(0).type = std::make_shared(6); + block.insert( + ColumnWithTypeAndName {nullptr, std::make_shared(), "result"}); + return block; + }; + + { + CastToImpl cast; + auto block = create_source_block(); + const auto status = cast.execute_impl(&context, block, arguments, result, block.rows()); + ASSERT_TRUE(status.ok()) << status.to_string(); + + const auto& nullable = + assert_cast(*block.get_by_position(result).column); + const auto& values = assert_cast(nullable.get_nested_column()); + EXPECT_TRUE(nullable.is_null_at(0)); + EXPECT_FALSE(nullable.is_null_at(1)); + EXPECT_FALSE(nullable.is_null_at(2)); + EXPECT_TRUE(nullable.is_null_at(3)); + EXPECT_EQ(values.get_element(1).to_string(), "1677-09-21 00:12:43.145225000"); + EXPECT_EQ(values.get_element(2).to_string(), "2262-04-11 23:47:16.854775000"); + } + + { + CastToImpl cast; + auto block = create_source_block(); + const auto status = cast.execute_impl(&context, block, arguments, result, block.rows()); + EXPECT_FALSE(status.ok()); + EXPECT_NE(status.to_string().find("can not cast timestamptz"), std::string::npos) + << status.to_string(); + } +} + TEST_F(CastTimeStampTzTest, from_timestamptz_strict_mode_to_datetime) { CastToImpl cast; diff --git a/be/test/exprs/function/function_test_util.cpp b/be/test/exprs/function/function_test_util.cpp index b37e452b69a52a..3d3ce825afc049 100644 --- a/be/test/exprs/function/function_test_util.cpp +++ b/be/test/exprs/function/function_test_util.cpp @@ -43,6 +43,7 @@ #include "core/data_type/data_type_string.h" #include "core/data_type/data_type_struct.h" #include "core/data_type/data_type_time.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/data_type/data_type_varbinary.h" #include "core/field.h" #include "core/types.h" @@ -197,6 +198,10 @@ static size_t type_index_to_data_type(const std::vector& input_types, s type = std::make_shared(input_types[index].scale_or(0)); desc = type; return 1; + case PrimitiveType::TYPE_TIMESTAMP_NS: + type = std::make_shared(); + desc = type; + return 1; case PrimitiveType::TYPE_TIMEV2: type = std::make_shared(input_types[index].scale_or(0)); desc = type; @@ -318,7 +323,16 @@ bool insert_datetime_cell(MutableColumnPtr& column, DataTypePtr date_type_ptr, c auto datetime_str = any_cast(cell); CastParameters params; - if constexpr (PType == PrimitiveType::TYPE_DATETIMEV2) { + if constexpr (PType == PrimitiveType::TYPE_TIMESTAMP_NS) { + StringRef value {datetime_str}; + result = date_type_ptr->get_serde() + ->from_string(value, *column, DataTypeSerDe::FormatOptions {}) + .ok(); + if (!result) { + column->insert_default(); + } + return result; + } else if constexpr (PType == PrimitiveType::TYPE_DATETIMEV2) { result = CastToDatetimeV2::from_string_non_strict_mode( {datetime_str.c_str(), datetime_str.size()}, date_value, nullptr, date_type_ptr->get_scale(), params); @@ -529,6 +543,11 @@ bool insert_cell(MutableColumnPtr& column, DataTypePtr type_ptr, const AnyType& column, type_ptr, cell, datetime_is_string_format))); break; } + case PrimitiveType::TYPE_TIMESTAMP_NS: { + RETURN_IF_FALSE((insert_datetime_cell( + column, type_ptr, cell, datetime_is_string_format))); + break; + } case PrimitiveType::TYPE_TIMEV2: { TimeValue::TimeType time_value = 0; if (datetime_is_string_format) { diff --git a/be/test/exprs/function/function_test_util.h b/be/test/exprs/function/function_test_util.h index ebbb9c2f77c486..95fa7b2b6be00e 100644 --- a/be/test/exprs/function/function_test_util.h +++ b/be/test/exprs/function/function_test_util.h @@ -50,6 +50,7 @@ #include "core/data_type/data_type_string.h" #include "core/data_type/data_type_struct.h" #include "core/data_type/data_type_time.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/data_type/data_type_varbinary.h" #include "core/extended_types.h" #include "core/types.h" @@ -157,6 +158,11 @@ struct ut_input_type { inline static type default_value = "1970-01-01"; }; template <> +struct ut_input_type { + using type = std::string; + inline static type default_value = "1970-01-01 00:00:00.000000000"; +}; +template <> struct ut_input_type { using type = std::string; inline static type default_value = "01:02:03"; @@ -271,6 +277,9 @@ DataTypePtr get_return_type_descriptor(int scale, int precision) { } else if (std::is_same_v) { return DataTypeFactory::instance().create_data_type(doris::PrimitiveType::TYPE_DATETIMEV2, false, precision, scale); + } else if (std::is_same_v) { + return DataTypeFactory::instance().create_data_type(doris::PrimitiveType::TYPE_TIMESTAMP_NS, + false); } else if (std::is_same_v) { return DataTypeFactory::instance().create_data_type(doris::PrimitiveType::TYPE_DECIMALV2, false, precision, scale); diff --git a/be/test/exprs/function/function_timestamp_ns_test.cpp b/be/test/exprs/function/function_timestamp_ns_test.cpp new file mode 100644 index 00000000000000..579952eb3aa1a7 --- /dev/null +++ b/be/test/exprs/function/function_timestamp_ns_test.cpp @@ -0,0 +1,242 @@ +// 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 "exprs/function/function_test_util.h" +#include "util/timezone_utils.h" + +namespace doris { +using namespace ut_type; + +TEST(TimestampNsFunctionTest, calendar_extract_and_format) { + const InputTypeSet one_argument = {{PrimitiveType::TYPE_TIMESTAMP_NS}}; + + EXPECT_TRUE((check_function( + "year", one_argument, + {{{std::string("1677-09-21 00:12:43.145224192")}, int16_t(1677)}, + {{std::string("1970-01-01 00:00:00.000000000")}, int16_t(1970)}, + {{std::string("2262-04-11 23:47:16.854775807")}, int16_t(2262)}}) + .ok())); + EXPECT_TRUE((check_function( + "to_days", one_argument, + {{{std::string("1677-09-21 00:12:43.145224192")}, int32_t(612776)}, + {{std::string("1970-01-01 00:00:00.000000000")}, int32_t(719528)}, + {{std::string("2262-04-11 23:47:16.854775807")}, int32_t(826279)}}) + .ok())); + + const InputTypeSet format_arguments = {{PrimitiveType::TYPE_TIMESTAMP_NS}, + Consted {PrimitiveType::TYPE_VARCHAR}}; + EXPECT_TRUE( + (check_function("date_format", format_arguments, + {{{std::string("2024-02-29 12:34:56.123456789"), + std::string("%Y-%m-%d %H:%i:%s.%f")}, + std::string("2024-02-29 12:34:56.123456")}}) + .ok())); + + EXPECT_TRUE((check_function( + "year_month", one_argument, + {{{std::string("2024-02-29 12:34:56.123456789")}, std::string("2024-02")}}) + .ok())); + EXPECT_TRUE( + (check_function("day_microsecond", one_argument, + {{{std::string("2024-02-29 12:34:56.123456789")}, + std::string("29 12:34:56.123456")}}) + .ok())); + EXPECT_TRUE((check_function( + "second_timestamp", one_argument, + {{{std::string("1970-01-01 00:00:00.999999999")}, int64_t(-28800)}}) + .ok())); +} + +TEST(TimestampNsFunctionTest, arithmetic_preserves_nanoseconds_and_checks_range) { + const InputTypeSet subday_arguments = {{PrimitiveType::TYPE_TIMESTAMP_NS}, + PrimitiveType::TYPE_BIGINT}; + + EXPECT_TRUE((check_function( + "seconds_add", subday_arguments, + {{{std::string("1969-12-31 23:59:59.999999999"), int64_t(1)}, + std::string("1970-01-01 00:00:00.999999999")}, + {{std::string("1970-01-01 00:00:00.000000001"), int64_t(-1)}, + std::string("1969-12-31 23:59:59.000000001")}}) + .ok())); + + EXPECT_TRUE((check_function( + "microseconds_add", subday_arguments, + {{{std::string("1677-09-21 00:12:43.145224192"), int64_t(1)}, + std::string("1677-09-21 00:12:43.145225192")}, + {{std::string("1970-01-01 00:00:00.999999999"), int64_t(1)}, + std::string("1970-01-01 00:00:01.000000999")}}) + .ok())); + + const InputTypeSet calendar_arguments = {{PrimitiveType::TYPE_TIMESTAMP_NS}, + PrimitiveType::TYPE_INT}; + EXPECT_TRUE((check_function( + "months_add", calendar_arguments, + {{{std::string("2024-01-31 12:34:56.123456789"), int32_t(1)}, + std::string("2024-02-29 12:34:56.123456789")}}) + .ok())); + EXPECT_TRUE((check_function( + "years_add", calendar_arguments, + {{{std::string("2024-02-29 12:34:56.123456789"), int32_t(1)}, + std::string("2025-02-28 12:34:56.123456789")}}) + .ok())); + + const InputTypeSet time_arguments = {{PrimitiveType::TYPE_TIMESTAMP_NS}, + {PrimitiveType::TYPE_TIMEV2, 6}}; + EXPECT_TRUE((check_function( + "add_time", time_arguments, + {{{std::string("1969-12-31 23:59:59.999999999"), + std::string("00:00:00.000001")}, + std::string("1970-01-01 00:00:00.000000999")}}) + .ok())); + EXPECT_TRUE((check_function( + "sub_time", time_arguments, + {{{std::string("1970-01-01 00:00:00.000000001"), + std::string("00:00:00.000001")}, + std::string("1969-12-31 23:59:59.999999001")}}) + .ok())); + + EXPECT_FALSE((check_function( + "seconds_add", subday_arguments, + {{{std::string("2262-04-11 23:47:16.854775807"), int64_t(1)}, + std::string("unused")}}, + -1, -1, true) + .ok())); + EXPECT_FALSE((check_function( + "months_add", calendar_arguments, + {{{std::string("1677-09-21 00:12:43.145224192"), int32_t(-1)}, + std::string("unused")}}, + -1, -1, true) + .ok())); + EXPECT_FALSE((check_function( + "years_add", calendar_arguments, + {{{std::string("2262-04-11 23:47:16.854775807"), int32_t(1)}, + std::string("unused")}}, + -1, -1, true) + .ok())); +} + +TEST(TimestampNsFunctionTest, differences_keep_submicrosecond_ordering) { + const InputTypeSet arguments = {{PrimitiveType::TYPE_TIMESTAMP_NS}, + {PrimitiveType::TYPE_TIMESTAMP_NS}}; + + EXPECT_TRUE( + (check_function("timediff", arguments, + {{{std::string("1970-01-01 00:00:00.000000000"), + std::string("1969-12-31 23:59:59.999999999")}, + std::string("0.0")}, + {{std::string("2024-02-29 12:34:56.123456789"), + std::string("2024-02-29 12:34:55.000000001")}, + std::string("00:00:01.123456")}}, + 6) + .ok())); + EXPECT_TRUE( + (check_function("microseconds_diff", arguments, + {{{std::string("1970-01-01 00:00:00.000001999"), + std::string("1970-01-01 00:00:00.000000000")}, + int64_t(1)}, + {{std::string("1969-12-31 23:59:59.999999999"), + std::string("1970-01-01 00:00:00.000000000")}, + int64_t(0)}}) + .ok())); + EXPECT_TRUE( + (check_function("months_diff", arguments, + {{{std::string("2024-03-29 12:34:56.123456789"), + std::string("2024-02-29 12:34:56.123456789")}, + int64_t(1)}, + {{std::string("2024-02-29 12:34:56.123456789"), + std::string("2024-03-29 12:34:56.123456789")}, + int64_t(-1)}}) + .ok())); +} + +TEST(TimestampNsFunctionTest, convert_tz_preserves_nanoseconds) { + TimezoneUtils::clear_timezone_caches(); + TimezoneUtils::load_timezones_to_cache(); + + const InputTypeSet arguments = {PrimitiveType::TYPE_TIMESTAMP_NS, PrimitiveType::TYPE_VARCHAR, + PrimitiveType::TYPE_VARCHAR}; + EXPECT_TRUE((check_function( + "convert_tz", arguments, + {{{std::string("2024-02-29 12:34:56.123456789"), + std::string("Asia/Shanghai"), std::string("UTC")}, + std::string("2024-02-29 04:34:56.123456789")}}) + .ok())); +} + +TEST(TimestampNsFunctionTest, trunc_floor_and_ceil) { + const InputTypeSet trunc_arguments = {{PrimitiveType::TYPE_TIMESTAMP_NS}, + Consted {PrimitiveType::TYPE_VARCHAR}}; + EXPECT_TRUE((check_function( + "date_trunc", trunc_arguments, + {{{std::string("2024-02-29 12:34:56.123456789"), std::string("second")}, + std::string("2024-02-29 12:34:56.000000000")}}) + .ok())); + + const InputTypeSet one_argument = {{PrimitiveType::TYPE_TIMESTAMP_NS}}; + EXPECT_TRUE((check_function( + "second_floor", one_argument, + {{{std::string("1969-12-31 23:59:59.999999999")}, + std::string("1969-12-31 23:59:59.000000000")}, + {{std::string("1970-01-01 00:00:00.000000001")}, + std::string("1970-01-01 00:00:00.000000000")}}) + .ok())); + EXPECT_TRUE((check_function( + "second_ceil", one_argument, + {{{std::string("1969-12-31 23:59:59.999999999")}, + std::string("1970-01-01 00:00:00.000000000")}}) + .ok())); + + EXPECT_FALSE((check_function( + "date_trunc", trunc_arguments, + {{{std::string("1677-09-21 00:12:43.145224192"), std::string("day")}, + std::string("unused")}}, + -1, -1, true) + .ok())); + EXPECT_FALSE((check_function( + "second_ceil", one_argument, + {{{std::string("2262-04-11 23:47:16.854775807")}, std::string("unused")}}, + -1, -1, true) + .ok())); +} + +TEST(TimestampNsFunctionTest, width_bucket_uses_epoch_nanoseconds) { + const InputTypeSet arguments = {{PrimitiveType::TYPE_TIMESTAMP_NS}, + {PrimitiveType::TYPE_TIMESTAMP_NS}, + {PrimitiveType::TYPE_TIMESTAMP_NS}, + {PrimitiveType::TYPE_TINYINT}}; + EXPECT_TRUE((check_function( + "width_bucket", arguments, + {{{std::string("2024-01-01 00:00:00.000000000"), + std::string("2024-01-01 00:00:00.000000000"), + std::string("2024-01-01 00:00:01.000000000"), int8_t(4)}, + int64_t(1)}, + {{std::string("2023-12-31 23:59:59.999999999"), + std::string("2024-01-01 00:00:00.000000000"), + std::string("2024-01-01 00:00:01.000000000"), int8_t(4)}, + int64_t(0)}, + {{std::string("2024-01-01 00:00:00.750000000"), + std::string("2024-01-01 00:00:00.000000000"), + std::string("2024-01-01 00:00:01.000000000"), int8_t(4)}, + int64_t(4)}, + {{std::string("2024-01-01 00:00:01.000000000"), + std::string("2024-01-01 00:00:00.000000000"), + std::string("2024-01-01 00:00:01.000000000"), int8_t(4)}, + int64_t(5)}}) + .ok())); +} + +} // namespace doris diff --git a/be/test/exprs/vcondition_expr_test.cpp b/be/test/exprs/vcondition_expr_test.cpp index b26f01cc2664c5..83b5ea26aa8fd9 100644 --- a/be/test/exprs/vcondition_expr_test.cpp +++ b/be/test/exprs/vcondition_expr_test.cpp @@ -29,8 +29,10 @@ #include "core/column/column_nullable.h" #include "core/column/column_vector.h" +#include "core/data_type/data_type_date_or_datetime_v2.h" #include "core/data_type/data_type_nullable.h" #include "core/data_type/data_type_number.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "exprs/vexpr.h" #include "exprs/vexpr_context.h" @@ -38,7 +40,7 @@ namespace doris { // Build a minimal TExprNode as the input of VectorizedCoalesceExpr. // Only fields required by the VExpr base ctor (so that create_data_type works) are set. -static TExprNode make_coalesce_node(TPrimitiveType::type ptype, bool is_nullable) { +static TExprNode make_coalesce_node(TPrimitiveType::type ptype, bool is_nullable, int scale = -1) { TExprNode node; node.node_type = TExprNodeType::FUNCTION_CALL; node.num_children = 0; @@ -49,6 +51,9 @@ static TExprNode make_coalesce_node(TPrimitiveType::type ptype, bool is_nullable type_node.type = TTypeNodeType::SCALAR; TScalarType scalar_type; scalar_type.__set_type(ptype); + if (scale >= 0) { + scalar_type.__set_scale(scale); + } type_node.__set_scalar_type(scalar_type); type_desc.types.push_back(type_node); node.__set_type(type_desc); @@ -355,4 +360,53 @@ TEST_F(VConditionExprCoalesceTest, Int32_NormalPathStillWorks) { EXPECT_FALSE(is_null); } +TEST_F(VConditionExprCoalesceTest, TimeStampNs) { + auto coalesce_node = + make_coalesce_node(TPrimitiveType::TIMESTAMP_NS, /*is_nullable=*/true, /*scale=*/9); + auto coalesce_expr = VectorizedCoalesceExpr::create_shared(coalesce_node); + auto nano_type = std::make_shared(); + coalesce_expr->data_type() = std::make_shared(nano_type); + + auto nested0 = ColumnTimeStampNs::create(); + nested0->insert_value(TimeStampNsValue(11)); + nested0->insert_value(TimeStampNsValue(0)); + nested0->insert_value(TimeStampNsValue(-17)); + nested0->insert_value(TimeStampNsValue(0)); + auto null_map0 = ColumnUInt8::create(); + null_map0->insert_value(0); + null_map0->insert_value(1); + null_map0->insert_value(0); + null_map0->insert_value(1); + ColumnPtr col0 = ColumnNullable::create(std::move(nested0), std::move(null_map0)); + + auto col1 = ColumnTimeStampNs::create(); + col1->insert_value(TimeStampNsValue(99)); + col1->insert_value(TimeStampNsValue(22)); + col1->insert_value(TimeStampNsValue(std::numeric_limits::max())); + col1->insert_value(TimeStampNsValue(std::numeric_limits::min())); + + coalesce_expr->add_child( + std::make_shared(col0, std::make_shared(nano_type))); + coalesce_expr->add_child(std::make_shared(std::move(col1), nano_type)); + + VExprContext context(coalesce_expr); + ColumnPtr result; + auto st = coalesce_expr->execute_column_impl(&context, /*block=*/nullptr, + /*selector=*/nullptr, /*count=*/4, result); + ASSERT_TRUE(st.ok()) << st.to_string(); + ASSERT_EQ(result->size(), 4); + + const auto& nullable = assert_cast(*result); + const auto& values = + assert_cast(nullable.get_nested_column()).get_data(); + EXPECT_FALSE(nullable.is_null_at(0)); + EXPECT_EQ(values[0].epoch_nanos(), 11); + EXPECT_FALSE(nullable.is_null_at(1)); + EXPECT_EQ(values[1].epoch_nanos(), 22); + EXPECT_FALSE(nullable.is_null_at(2)); + EXPECT_EQ(values[2].epoch_nanos(), -17); + EXPECT_FALSE(nullable.is_null_at(3)); + EXPECT_EQ(values[3].epoch_nanos(), std::numeric_limits::min()); +} + } // namespace doris diff --git a/be/test/exprs/vexpr_unaligned_int128_test.cpp b/be/test/exprs/vexpr_unaligned_int128_test.cpp index d34a6da7f9430a..844c5fc633e463 100644 --- a/be/test/exprs/vexpr_unaligned_int128_test.cpp +++ b/be/test/exprs/vexpr_unaligned_int128_test.cpp @@ -34,6 +34,7 @@ #include "core/value/decimalv2_value.h" #include "core/value/large_int_value.h" +#include "core/value/timestamp_ns_value.h" #include "exprs/vexpr.h" namespace doris { @@ -104,4 +105,14 @@ TEST(UnalignedInt128Test, DecimalV2LiteralFromUnalignedBuffer) { EXPECT_EQ(node.decimal_literal.value, src.to_string()); } +TEST(UnalignedInt128Test, TimeStampNsLiteralKeepsItsPhysicalType) { + const TimeStampNsValue value(1); + TExprNode node; + Status st = create_texpr_literal_node(&value, &node); + ASSERT_TRUE(st.ok()) << st; + ASSERT_TRUE(node.__isset.date_literal); + ASSERT_EQ(node.type.types.size(), 1); + EXPECT_EQ(node.type.types.front().scalar_type.type, TPrimitiveType::TIMESTAMP_NS); +} + } // namespace doris diff --git a/be/test/format/orc/orc_reader_fill_data_test.cpp b/be/test/format/orc/orc_reader_fill_data_test.cpp index 44177ddb29df46..028b786d3efdfc 100644 --- a/be/test/format/orc/orc_reader_fill_data_test.cpp +++ b/be/test/format/orc/orc_reader_fill_data_test.cpp @@ -17,6 +17,7 @@ #include +#include #include #include "core/assert_cast.h" @@ -28,6 +29,7 @@ #include "core/data_type/data_type_map.h" #include "core/data_type/data_type_number.h" #include "core/data_type/data_type_struct.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/types.h" #include "format/orc/orc_memory_stream_test.h" #include "format/orc/vorc_reader.h" @@ -161,6 +163,55 @@ TEST_F(OrcReaderFillDataTest, TimestampDecodeNormalizesCstTimezone) { EXPECT_EQ(data_type->to_string(timestamp_column.get_data()[0]), "2020-01-02 03:04:05.321000"); } +TEST_F(OrcReaderFillDataTest, TimestampDecodeKeepsWideDateTimeV2Range) { + auto batch = create_timestamp_batch(1, {253402300799}, {999999000}); + auto data_type = std::make_shared(6); + auto column = data_type->create_column(); + auto orc_type_ptr = createPrimitiveType(orc::TypeKind::TIMESTAMP); + + TFileScanRangeParams params; + TFileRangeDesc range; + auto reader = OrcReader::create_unique(params, range, 4064, "UTC", nullptr, nullptr, true); + + MutableColumnPtr mutable_column = column->assert_mutable(); + Status status = reader->_fill_doris_data_column( + "test_ts", mutable_column, data_type, const_node, orc_type_ptr.get(), batch.get(), 1); + + ASSERT_TRUE(status.ok()) << status.to_string(); + const auto& timestamp_column = assert_cast(*mutable_column); + ASSERT_EQ(timestamp_column.size(), 1); + EXPECT_EQ(data_type->to_string(timestamp_column.get_data()[0]), "9999-12-31 23:59:59.999999"); +} + +TEST_F(OrcReaderFillDataTest, TimestampNsDecodeKeepsNanosecondsAndRejectsOverflow) { + auto batch = create_timestamp_batch(3, {-1, 0, 9223372036}, {999999999, 123456789, 854775807}); + auto data_type = std::make_shared(); + auto column = data_type->create_column(); + auto orc_type_ptr = createPrimitiveType(orc::TypeKind::TIMESTAMP); + + TFileScanRangeParams params; + TFileRangeDesc range; + auto reader = OrcReader::create_unique(params, range, 4064, "UTC", nullptr, nullptr, true); + + MutableColumnPtr mutable_column = column->assert_mutable(); + Status status = + reader->_fill_doris_data_column("test_ts_ns", mutable_column, data_type, + const_node, orc_type_ptr.get(), batch.get(), 3); + + ASSERT_TRUE(status.ok()) << status.to_string(); + const auto& timestamp_column = assert_cast(*mutable_column); + ASSERT_EQ(timestamp_column.size(), 3); + EXPECT_EQ(timestamp_column.get_data()[0].epoch_nanos(), -1); + EXPECT_EQ(timestamp_column.get_data()[1].epoch_nanos(), 123456789); + EXPECT_EQ(timestamp_column.get_data()[2].epoch_nanos(), std::numeric_limits::max()); + + auto overflow_batch = create_timestamp_batch(1, {9223372036}, {854775808}); + status = reader->_fill_doris_data_column("overflow_ts_ns", mutable_column, data_type, + const_node, orc_type_ptr.get(), + overflow_batch.get(), 1); + EXPECT_FALSE(status.ok()); +} + TEST_F(OrcReaderFillDataTest, SchemaChangeNullableNullMapUsesAppendedSlice) { std::vector values = {10, 20, 30}; std::vector nulls = {true, false, true}; diff --git a/be/test/format/parquet/parquet_column_convert_test.cpp b/be/test/format/parquet/parquet_column_convert_test.cpp index 112390442dc593..b84a0000587323 100644 --- a/be/test/format/parquet/parquet_column_convert_test.cpp +++ b/be/test/format/parquet/parquet_column_convert_test.cpp @@ -26,6 +26,7 @@ #include "core/column/column_fixed_length_object.h" #include "core/column/column_nullable.h" #include "core/column/column_vector.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "util/timezone_utils.h" namespace doris::parquet { @@ -160,6 +161,73 @@ TEST(ParquetColumnConvertTest, AlignNullMapUsesAppendedSourceSlice) { EXPECT_EQ(null_map[4], 1); } +TEST(ParquetColumnConvertTest, ConvertsTimestampNanosWithoutPrecisionLoss) { + auto field_schema = make_timestamp_field_schema(false); + field_schema.parquet_schema.__set_type(tparquet::Type::INT64); + field_schema.parquet_schema.logicalType.TIMESTAMP.unit = tparquet::TimeUnit(); + field_schema.parquet_schema.logicalType.TIMESTAMP.unit.__set_NANOS(tparquet::NanoSeconds()); + field_schema.data_type = std::make_shared(); + + auto converter = PhysicalToLogicalConverter::get_converter( + &field_schema, field_schema.data_type, field_schema.data_type, nullptr); + ASSERT_TRUE(converter->support()) << converter->get_error_msg(); + + auto physical = ColumnInt64::create(); + physical->insert_value(std::numeric_limits::min()); + physical->insert_value(-1); + physical->insert_value(0); + physical->insert_value(123456789); + physical->insert_value(std::numeric_limits::max()); + ColumnPtr source = std::move(physical); + ColumnPtr destination = field_schema.data_type->create_column(); + + ASSERT_TRUE(converter + ->convert(source, field_schema.data_type, field_schema.data_type, + destination, false) + .ok()); + const auto& data = assert_cast(*destination).get_data(); + ASSERT_EQ(data.size(), 5); + EXPECT_EQ(data[0].epoch_nanos(), std::numeric_limits::min()); + EXPECT_EQ(data[1].epoch_nanos(), -1); + EXPECT_EQ(data[2].epoch_nanos(), 0); + EXPECT_EQ(data[3].epoch_nanos(), 123456789); + EXPECT_EQ(data[4].epoch_nanos(), std::numeric_limits::max()); +} + +TEST(ParquetColumnConvertTest, ConvertsAdjustedTimestampNanosToSessionCivilTime) { + auto field_schema = make_timestamp_field_schema(true); + field_schema.parquet_schema.__set_type(tparquet::Type::INT64); + field_schema.parquet_schema.logicalType.TIMESTAMP.unit = tparquet::TimeUnit(); + field_schema.parquet_schema.logicalType.TIMESTAMP.unit.__set_NANOS(tparquet::NanoSeconds()); + field_schema.data_type = std::make_shared(); + const cctz::time_zone plus_eight = cctz::fixed_time_zone(cctz::seconds(8 * 3600)); + + auto converter = PhysicalToLogicalConverter::get_converter( + &field_schema, field_schema.data_type, field_schema.data_type, &plus_eight); + ASSERT_TRUE(converter->support()) << converter->get_error_msg(); + + auto physical = ColumnInt64::create(); + physical->insert_value(0); + ColumnPtr source = std::move(physical); + ColumnPtr destination = field_schema.data_type->create_column(); + ASSERT_TRUE(converter + ->convert(source, field_schema.data_type, field_schema.data_type, + destination, false) + .ok()); + const auto& data = assert_cast(*destination).get_data(); + ASSERT_EQ(data.size(), 1); + EXPECT_EQ(data[0].epoch_nanos(), 8LL * 3600 * TimeStampNsValue::NANOS_PER_SECOND); + + auto overflowing_physical = ColumnInt64::create(); + overflowing_physical->insert_value(std::numeric_limits::max()); + ColumnPtr overflowing_source = std::move(overflowing_physical); + ColumnPtr overflowing_destination = field_schema.data_type->create_column(); + EXPECT_TRUE(converter + ->convert(overflowing_source, field_schema.data_type, + field_schema.data_type, overflowing_destination, false) + .is()); +} + TEST(ParquetColumnConvertTest, AlignNullMapUsesNullablePrefixForCachedReadColumn) { auto dst_nested_column = ColumnFloat64::create(); dst_nested_column->insert_value(1); diff --git a/be/test/format/parquet/parquet_thrift_test.cpp b/be/test/format/parquet/parquet_thrift_test.cpp index 0fe101db598138..e49a5d3809ac3e 100644 --- a/be/test/format/parquet/parquet_thrift_test.cpp +++ b/be/test/format/parquet/parquet_thrift_test.cpp @@ -96,6 +96,28 @@ TEST_F(ParquetThriftReaderTest, normal) { } } +TEST_F(ParquetThriftReaderTest, timestampNanosMapsToTimestampNs) { + tparquet::SchemaElement root; + root.__set_name("schema"); + root.__set_num_children(1); + + tparquet::SchemaElement timestamp; + timestamp.__set_name("ts_ns"); + timestamp.__set_type(tparquet::Type::INT64); + timestamp.__set_repetition_type(tparquet::FieldRepetitionType::OPTIONAL); + timestamp.__set_logicalType(tparquet::LogicalType()); + timestamp.logicalType.__set_TIMESTAMP(tparquet::TimestampType()); + timestamp.logicalType.TIMESTAMP.__set_isAdjustedToUTC(false); + timestamp.logicalType.TIMESTAMP.__set_unit(tparquet::TimeUnit()); + timestamp.logicalType.TIMESTAMP.unit.__set_NANOS(tparquet::NanoSeconds()); + + FieldDescriptor descriptor; + ASSERT_TRUE(descriptor.parse_from_thrift({root, timestamp}).ok()); + ASSERT_EQ(descriptor.size(), 1); + EXPECT_EQ(remove_nullable(descriptor.get_column(0)->data_type)->get_primitive_type(), + TYPE_TIMESTAMP_NS); +} + TEST_F(ParquetThriftReaderTest, complex_nested_file) { // hive-complex.parquet is the part of following table: // complex_nested_table( diff --git a/be/test/format/table/iceberg/iceberg_reader_test.cpp b/be/test/format/table/iceberg/iceberg_reader_test.cpp index ef1c469ca23808..d3334f4bfb6716 100644 --- a/be/test/format/table/iceberg/iceberg_reader_test.cpp +++ b/be/test/format/table/iceberg/iceberg_reader_test.cpp @@ -1766,6 +1766,10 @@ TEST_F(IcebergReaderTest, initial_default_normalizes_timestamp_for_doris) { iceberg::detail::normalize_timestamp_for_doris(TYPE_TIMESTAMPTZ, ×tamp_tz); EXPECT_EQ(timestamp_tz, "2026-07-24 12:34:56.123456+08:00"); + std::string timestamp_ns = "2026-07-24T12:34:56.123456789+08:00"; + iceberg::detail::normalize_timestamp_for_doris(TYPE_TIMESTAMP_NS, ×tamp_ns); + EXPECT_EQ(timestamp_ns, "2026-07-24 12:34:56.123456789"); + std::string date = "2026-07-24"; iceberg::detail::normalize_timestamp_for_doris(TYPE_DATETIME, &date); EXPECT_EQ(date, "2026-07-24"); diff --git a/be/test/format/table/iceberg/type_test.cpp b/be/test/format/table/iceberg/type_test.cpp index 81f8b6b760c24f..3cabec7422c9a2 100644 --- a/be/test/format/table/iceberg/type_test.cpp +++ b/be/test/format/table/iceberg/type_test.cpp @@ -68,6 +68,16 @@ TEST(TimestampTypeTest, to_string) { EXPECT_EQ(timestamp_type_without_utc.type_id(), TypeID::TIMESTAMP); } +TEST(TimestampNanoTypeTest, to_string) { + TimestampNanoType timestamp_type_with_utc(true); + EXPECT_EQ(timestamp_type_with_utc.to_string(), "timestamptz_ns"); + EXPECT_EQ(timestamp_type_with_utc.type_id(), TypeID::TIMESTAMP_NANO); + + TimestampNanoType timestamp_type_without_utc(false); + EXPECT_EQ(timestamp_type_without_utc.to_string(), "timestamp_ns"); + EXPECT_EQ(timestamp_type_without_utc.type_id(), TypeID::TIMESTAMP_NANO); +} + TEST(TimeTypeTest, to_string) { TimeType time_type; EXPECT_EQ(time_type.to_string(), "time"); @@ -120,6 +130,8 @@ TEST(PrimitiveTypesTest, from_primitive_string) { EXPECT_EQ(Types::from_primitive_string("time")->type_id(), TypeID::TIME); EXPECT_EQ(Types::from_primitive_string("timestamptz")->type_id(), TypeID::TIMESTAMP); EXPECT_EQ(Types::from_primitive_string("timestamp")->type_id(), TypeID::TIMESTAMP); + EXPECT_EQ(Types::from_primitive_string("timestamptz_ns")->type_id(), TypeID::TIMESTAMP_NANO); + EXPECT_EQ(Types::from_primitive_string("timestamp_ns")->type_id(), TypeID::TIMESTAMP_NANO); EXPECT_EQ(Types::from_primitive_string("string")->type_id(), TypeID::STRING); EXPECT_EQ(Types::from_primitive_string("uuid")->type_id(), TypeID::UUID); EXPECT_EQ(Types::from_primitive_string("binary")->type_id(), TypeID::BINARY); diff --git a/be/test/format_v2/column_mapper_test.cpp b/be/test/format_v2/column_mapper_test.cpp index e6884f8fd81e06..729c9500190d70 100644 --- a/be/test/format_v2/column_mapper_test.cpp +++ b/be/test/format_v2/column_mapper_test.cpp @@ -1234,6 +1234,7 @@ TEST(ColumnMapperScanRequestTest, FullProjectionRetainsOnlyTimestampSemanticPath auto file_timestamp = field_id_col("ts", 2, timestamptz(6), 0); file_timestamp.timestamp_is_adjusted_to_utc = true; + file_timestamp.timestamp_is_nanosecond = true; auto file_payload = field_id_col("payload", 3, i32(), 1); auto file_event = struct_col("event", 1, {file_timestamp, file_payload}, 0); auto file_other = field_id_col("other", 4, i32(), 1); @@ -1255,6 +1256,7 @@ TEST(ColumnMapperScanRequestTest, FullProjectionRetainsOnlyTimestampSemanticPath EXPECT_EQ(timestamp_projection.local_id(), 0); ASSERT_TRUE(timestamp_projection.timestamp_is_adjusted_to_utc.has_value()); EXPECT_TRUE(*timestamp_projection.timestamp_is_adjusted_to_utc); + EXPECT_TRUE(timestamp_projection.timestamp_is_nanosecond); } // Scenario: array/map nested projections also scan the full top-level complex root for diff --git a/be/test/format_v2/jni/jni_table_reader_test.cpp b/be/test/format_v2/jni/jni_table_reader_test.cpp index 43064d8147a85e..ec42d73b9d8047 100644 --- a/be/test/format_v2/jni/jni_table_reader_test.cpp +++ b/be/test/format_v2/jni/jni_table_reader_test.cpp @@ -20,6 +20,8 @@ #include #include +#include +#include #include #include #include @@ -30,6 +32,7 @@ #include "core/data_type/data_type_number.h" #include "core/data_type/data_type_string.h" #include "core/data_type/data_type_struct.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "exprs/vexpr_context.h" #include "exprs/vslot_ref.h" #include "format/jni/jni_data_bridge.h" @@ -124,6 +127,30 @@ TEST(JniTableReaderTest, RequiredFieldEncodingPreservesQuotedIdentifiers) { EXPECT_EQ(JniDataBridge::encode_schema_values({""}), "$"); } +TEST(JniTableReaderTest, TimestampNsUsesExactJniTypeDescriptor) { + const auto type = std::make_shared(); + EXPECT_EQ(JniDataBridge::get_jni_type(type), "timestamp_ns"); + EXPECT_EQ(JniDataBridge::get_jni_type_with_different_string(type), "timestamp_ns"); + EXPECT_EQ(JniDataBridge::get_jni_type_with_encoded_struct_fields(type), "timestamp_ns"); +} + +TEST(JniTableReaderTest, FillTimestampNsColumnPreservesEpochNanoseconds) { + const int64_t values[] = {std::numeric_limits::min(), -1, 0, 1, + std::numeric_limits::max()}; + const uint8_t null_map[] = {0, 0, 0, 0, 0}; + long meta[] = {reinterpret_cast(null_map), reinterpret_cast(values)}; + JniDataBridge::TableMetaAddress address(reinterpret_cast(meta)); + const auto type = std::make_shared(); + ColumnPtr column = type->create_column(); + + ASSERT_TRUE(JniDataBridge::fill_column(address, column, type, std::size(values)).ok()); + const auto& data = assert_cast(*column).get_data(); + ASSERT_EQ(data.size(), std::size(values)); + for (size_t i = 0; i < std::size(values); ++i) { + EXPECT_EQ(data[i].epoch_nanos(), values[i]); + } +} + TEST(JniTableReaderTest, EncodedTypeDescriptorsPreserveNestedQuotedIdentifiers) { auto type = std::make_shared( DataTypes {std::make_shared(), std::make_shared(), diff --git a/be/test/format_v2/parquet/native_decoder_test.cpp b/be/test/format_v2/parquet/native_decoder_test.cpp index af4a17d1b8a418..bbd523505634ef 100644 --- a/be/test/format_v2/parquet/native_decoder_test.cpp +++ b/be/test/format_v2/parquet/native_decoder_test.cpp @@ -37,6 +37,7 @@ #include "core/data_type/data_type_number.h" #include "core/data_type/data_type_string.h" #include "core/data_type/data_type_struct.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/data_type/data_type_timestamptz.h" #include "core/data_type_serde/parquet_decode_source.h" #include "core/data_type_serde/parquet_timestamp.h" @@ -4788,6 +4789,7 @@ TEST(ParquetV2NativeDecoderTest, DictionaryGatherSupportsEverySimdFixedWidthColu expect_fixed_width_dictionary_gather(); expect_fixed_width_dictionary_gather(); expect_fixed_width_dictionary_gather(); + expect_fixed_width_dictionary_gather(); expect_fixed_width_dictionary_gather(); expect_fixed_width_dictionary_gather(); expect_fixed_width_dictionary_gather(); diff --git a/be/test/format_v2/parquet/parquet_reader_test.cpp b/be/test/format_v2/parquet/parquet_reader_test.cpp index be6837755b1abf..080fb6d939b773 100644 --- a/be/test/format_v2/parquet/parquet_reader_test.cpp +++ b/be/test/format_v2/parquet/parquet_reader_test.cpp @@ -1111,10 +1111,10 @@ void write_nested_complex_under_struct_parquet_file(const std::string& file_path } void write_int96_timestamp_parquet_file(const std::string& file_path) { - auto field = arrow::field("ts_tz", arrow::timestamp(arrow::TimeUnit::MICRO), true); - auto array = - build_timestamp_array(arrow::timestamp(arrow::TimeUnit::MICRO), - {1735660800000000LL, 1735660800123456LL, 1735689600000000LL}); + auto field = arrow::field("ts_tz", arrow::timestamp(arrow::TimeUnit::NANO), true); + auto array = build_timestamp_array( + arrow::timestamp(arrow::TimeUnit::NANO), + {1735660800000000000LL, 1735660800123456789LL, 1735689600000000000LL}); auto table = arrow::Table::Make(arrow::schema({field}), {array}); auto file_result = arrow::io::FileOutputStream::Open(file_path); @@ -2272,6 +2272,35 @@ TEST_F(NewParquetReaderTest, Int96UsesPerColumnPaimonTimestampSemantics) { EXPECT_EQ(read_first_value(true), "2024-12-31 16:00:00.000000+00:00"); } +TEST_F(NewParquetReaderTest, Int96UsesPaimonNanosecondTimestampSemantics) { + write_int96_timestamp_parquet_file(_file_path); + + auto reader = create_reader(); + RuntimeState state {TQueryOptions(), TQueryGlobals()}; + state.set_timezone("Asia/Shanghai"); + ASSERT_TRUE(reader->init(&state).ok()); + + std::vector schema; + ASSERT_TRUE(reader->get_schema(&schema).ok()); + ASSERT_EQ(schema.size(), 1); + schema[0].type = DataTypeFactory::instance().create_data_type(TYPE_TIMESTAMP_NS, true); + + auto projection = field_projection(0); + projection.timestamp_is_adjusted_to_utc = false; + projection.timestamp_is_nanosecond = true; + auto request = std::make_shared(); + request->non_predicate_columns = {projection}; + ASSERT_TRUE(reader->open(request).ok()); + + Block block = build_file_block(schema); + size_t rows = 0; + bool eof = false; + ASSERT_TRUE(reader->get_block(&block, &rows, &eof).ok()); + ASSERT_EQ(rows, 3); + EXPECT_EQ(block.get_by_position(0).type->to_string(*block.get_by_position(0).column, 1), + "2024-12-31 16:00:00.123456789"); +} + TEST_F(NewParquetReaderTest, NestedInt96UsesHiveParquetTimezone) { TimezoneUtils::load_timezones_to_cache(); write_nested_int96_timestamp_parquet_file(_file_path); diff --git a/be/test/format_v2/parquet/parquet_schema_test.cpp b/be/test/format_v2/parquet/parquet_schema_test.cpp index 74781c0e532b31..63b794fc111d87 100644 --- a/be/test/format_v2/parquet/parquet_schema_test.cpp +++ b/be/test/format_v2/parquet/parquet_schema_test.cpp @@ -126,6 +126,28 @@ TEST(ParquetSchemaTest, NativeLogicalUtcTimeIsDeferredToProjectionValidation) { "Parquet TIME with isAdjustedToUTC=true is not supported"); } +TEST(ParquetSchemaTest, NativeTimestampNanosMapsToTimestampNs) { + tparquet::SchemaElement root; + root.__set_name("schema"); + root.__set_num_children(1); + + tparquet::SchemaElement timestamp; + timestamp.__set_name("ts_ns"); + timestamp.__set_type(tparquet::Type::INT64); + timestamp.__set_repetition_type(tparquet::FieldRepetitionType::OPTIONAL); + timestamp.__set_logicalType(tparquet::LogicalType()); + timestamp.logicalType.__set_TIMESTAMP(tparquet::TimestampType()); + timestamp.logicalType.TIMESTAMP.__set_isAdjustedToUTC(false); + timestamp.logicalType.TIMESTAMP.__set_unit(tparquet::TimeUnit()); + timestamp.logicalType.TIMESTAMP.unit.__set_NANOS(tparquet::NanoSeconds()); + + NativeFieldDescriptor descriptor; + ASSERT_TRUE(descriptor.parse_from_thrift({root, timestamp}).ok()); + ASSERT_EQ(descriptor.size(), 1); + EXPECT_EQ(remove_nullable(descriptor.get_column(0)->data_type)->get_primitive_type(), + TYPE_TIMESTAMP_NS); +} + TEST(ParquetSchemaTest, NativeOversizedByteArrayDecimalIsDeferredToProjectionValidation) { tparquet::SchemaElement root; root.__set_name("schema"); diff --git a/be/test/format_v2/table/paimon_reader_test.cpp b/be/test/format_v2/table/paimon_reader_test.cpp index 47e9031bf792fa..3d5fe292c90ab6 100644 --- a/be/test/format_v2/table/paimon_reader_test.cpp +++ b/be/test/format_v2/table/paimon_reader_test.cpp @@ -449,6 +449,9 @@ TEST(PaimonReaderTest, AnnotatesArrayAndMapFileSchemaFromSplitHistorySchema) { TEST(PaimonReaderTest, AnnotatesTimestampSemanticsFromSplitHistorySchema) { auto timestamp = external_schema_field("ts", 10); timestamp.field_ptr->__set_timestamp_is_adjusted_to_utc(false); + TColumnType timestamp_ns_type; + timestamp_ns_type.__set_type(TPrimitiveType::TIMESTAMP_NS); + timestamp.field_ptr->__set_type(timestamp_ns_type); auto timestamp_ltz = external_schema_field("ts_ltz", 11); timestamp_ltz.field_ptr->__set_timestamp_is_adjusted_to_utc(true); @@ -472,10 +475,25 @@ TEST(PaimonReaderTest, AnnotatesTimestampSemanticsFromSplitHistorySchema) { ASSERT_TRUE(file_schema[0].timestamp_is_adjusted_to_utc.has_value()); EXPECT_FALSE(*file_schema[0].timestamp_is_adjusted_to_utc); - EXPECT_EQ(remove_nullable(file_schema[0].type)->get_primitive_type(), TYPE_DATETIMEV2); + EXPECT_TRUE(file_schema[0].timestamp_is_nanosecond); + EXPECT_EQ(remove_nullable(file_schema[0].type)->get_primitive_type(), TYPE_TIMESTAMP_NS); ASSERT_TRUE(file_schema[1].timestamp_is_adjusted_to_utc.has_value()); EXPECT_TRUE(*file_schema[1].timestamp_is_adjusted_to_utc); EXPECT_EQ(remove_nullable(file_schema[1].type)->get_primitive_type(), TYPE_TIMESTAMPTZ); + + paimon::PaimonReader orc_reader; + orc_reader.TEST_set_scan_params(&scan_params); + split_options.current_split_format = FileFormat::ORC; + ASSERT_TRUE(orc_reader.prepare_split(split_options).ok()); + + std::vector orc_file_schema { + make_file_column(0, "ts", datetime_type), + make_file_column(1, "ts_ltz", datetime_type), + }; + ASSERT_TRUE(orc_reader.TEST_annotate_file_schema(&orc_file_schema).ok()); + EXPECT_TRUE(orc_file_schema[0].timestamp_is_nanosecond); + EXPECT_EQ(remove_nullable(orc_file_schema[0].type)->get_primitive_type(), TYPE_DATETIMEV2); + EXPECT_EQ(remove_nullable(orc_file_schema[1].type)->get_primitive_type(), TYPE_DATETIMEV2); } // Scenario: when FE does not send a matching historical schema for the split schema id, Paimon must diff --git a/be/test/runtime/runtime_predicate_test.cpp b/be/test/runtime/runtime_predicate_test.cpp index baf27e72ddc859..c29ab104cdf4a0 100644 --- a/be/test/runtime/runtime_predicate_test.cpp +++ b/be/test/runtime/runtime_predicate_test.cpp @@ -24,6 +24,7 @@ #include "core/data_type/data_type_factory.hpp" #include "core/data_type/data_type_number.h" #include "core/field.h" +#include "core/value/timestamp_ns_value.h" #include "exec/pipeline/thrift_builder.h" #include "exprs/expr_zonemap_filter.h" #include "exprs/vexpr_context.h" @@ -229,6 +230,25 @@ TEST(RuntimePredicateTest, TopNPredicateKeepsDirectCapabilityBeforeFirstBound) { context->close(); } +TEST(RuntimePredicateTest, TopNPredicateFiltersTimestampNsRawValues) { + MockRuntimeState state; + const auto type = DataTypeFactory::instance().create_data_type(TYPE_TIMESTAMP_NS, false); + auto context = create_prepared_topn_expr( + &state, type, Field::create_field(TimeStampNsValue(0))); + const std::array values {TimeStampNsValue(-1), TimeStampNsValue(0), + TimeStampNsValue(1)}; + IColumn::Filter matches(values.size(), 1); + + ASSERT_TRUE(context->root()->can_execute_on_raw_fixed_values(type, 0)); + ASSERT_TRUE(context->root() + ->execute_on_raw_fixed_values( + reinterpret_cast(values.data()), values.size(), + sizeof(TimeStampNsValue), type, 0, matches.data()) + .ok()); + EXPECT_EQ(matches, (IColumn::Filter {1, 1, 0})); + context->close(); +} + TEST(RuntimePredicateTest, TopNPredicateAdvertisesDirectCapabilityForEverySupportedType) { struct TypeSpec { PrimitiveType type; @@ -236,7 +256,7 @@ TEST(RuntimePredicateTest, TopNPredicateAdvertisesDirectCapabilityForEverySuppor int scale = 0; bool binary = false; }; - const std::array supported_types {{ + const std::array supported_types {{ {TYPE_BOOLEAN}, {TYPE_TINYINT}, {TYPE_SMALLINT}, @@ -247,6 +267,7 @@ TEST(RuntimePredicateTest, TopNPredicateAdvertisesDirectCapabilityForEverySuppor {TYPE_DATETIME}, {TYPE_DATEV2}, {TYPE_DATETIMEV2}, + {TYPE_TIMESTAMP_NS}, {TYPE_TIMESTAMPTZ}, {TYPE_TIMEV2}, {TYPE_DECIMAL32, 9, 2}, diff --git a/be/test/storage/key/row_key_encoder_test.cpp b/be/test/storage/key/row_key_encoder_test.cpp index 2a330c934e8334..665fb9ad4bb05f 100644 --- a/be/test/storage/key/row_key_encoder_test.cpp +++ b/be/test/storage/key/row_key_encoder_test.cpp @@ -494,7 +494,7 @@ struct SeqCase { // The FE allows sequence columns of isFixedPointType() || isDateType() // (PropertyAnalyzer::analyzeSequenceType and the sequence_col mapping share -// the check): the five integer types plus all five date types. BOOL is NOT +// the check): the five integer types plus all six date types. BOOL is NOT // seq-eligible. DATE and DATETIME remain here for legacy TabletSchemas even // though newly created tables use their v2 counterparts. std::vector seq_cases() { @@ -540,6 +540,8 @@ std::vector seq_cases() { fill_raw(c, 2, datetimev2_bits(2024, 6, 15, 12, 30, 45)); }, "01fa19ec7ad00000"}, + {"timestamp_ns", FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS, 8, + [](MutableColumns& c) { fill_raw(c, 2, 5); }, "8000000000000005"}, }; } @@ -1071,6 +1073,63 @@ TEST_F(RowKeyEncoderTest, SeqSuffix) { } } +// TIMESTAMP_NS is a signed epoch-nanosecond Int64. Verify that every table +// model uses its monotonic Int64 key coding for full and short keys, and that +// the MOW primary-key view uses exactly the same bytes. +TEST_F(RowKeyEncoderTest, TimestampNsKeyEncodingAllTableModels) { + struct SchemaCase { + const char* name; + KeysType keys_type; + bool mow; + }; + constexpr std::array kSchemaCases = {{ + {"duplicate_keys", DUP_KEYS, false}, + {"aggregate_keys", AGG_KEYS, false}, + {"unique_keys_merge_on_read", UNIQUE_KEYS, false}, + {"unique_keys_merge_on_write", UNIQUE_KEYS, true}, + }}; + constexpr std::array kValues = {std::numeric_limits::min(), -1, 0, 1, + std::numeric_limits::max()}; + constexpr std::array kExpectedKeys = { + "020000000000000000", "027fffffffffffffff", "028000000000000000", "028000000000000001", + "02ffffffffffffffff"}; + + for (const auto& schema_case : kSchemaCases) { + SCOPED_TRACE(schema_case.name); + auto schema = std::make_shared(); + auto key_column = make_key_column(0, FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS, + sizeof(int64_t), sizeof(int64_t)); + key_column->_is_nullable = false; + schema->append_column(*key_column); + schema->_keys_type = schema_case.keys_type; + schema->_num_short_key_columns = 1; + build(schema, kValues.size(), [&](MutableColumns& columns) { + for (const auto value : kValues) { + fill_raw(columns, 0, value); + } + }); + + RowKeyEncoder encoder(*schema, schema_case.mow); + std::vector key_columns {acc(0)}; + std::string previous_key; + for (size_t row = 0; row < kValues.size(); ++row) { + const std::string full_key = encoder.full_encode(key_columns, row); + const std::string short_key = encoder.encode_short_keys(key_columns, row); + EXPECT_EQ(to_hex(full_key), kExpectedKeys[row]); + EXPECT_EQ(short_key, full_key); + if (schema_case.mow) { + EXPECT_EQ(encoder.full_encode_primary_keys(key_columns, row), full_key); + } else { + EXPECT_TRUE(encoder.full_encode_primary_keys({}, row).empty()); + } + if (row > 0) { + EXPECT_LT(previous_key, full_key); + } + previous_key = full_key; + } + } +} + // full_encode_primary_keys() is the primary key index's view. With cluster keys the segment sorts // by those instead, so this is where the two views come apart: the probe side must encode the // primary key columns, not whatever full_encode() happens to give. diff --git a/be/test/storage/key_coder_test.cpp b/be/test/storage/key_coder_test.cpp index 5362645078677c..ee521f3a86df54 100644 --- a/be/test/storage/key_coder_test.cpp +++ b/be/test/storage/key_coder_test.cpp @@ -174,6 +174,7 @@ TEST_F(KeyCoderTest, test_int) { test_integer_encode(); test_integer_encode(); + test_integer_encode(); } TEST_F(KeyCoderTest, test_date) { diff --git a/be/test/storage/partial_update_info_test.cpp b/be/test/storage/partial_update_info_test.cpp new file mode 100644 index 00000000000000..38b1c7f33ee623 --- /dev/null +++ b/be/test/storage/partial_update_info_test.cpp @@ -0,0 +1,76 @@ +// 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 "storage/partial_update_info.h" + +#include + +#include +#include + +#include "storage/tablet/tablet_schema.h" + +namespace doris { +namespace { + +TabletColumn make_column(std::string name, FieldType type, bool is_key, + const std::string& default_value = {}) { + TabletColumn column(FieldAggregationMethod::OLAP_FIELD_AGGREGATION_NONE, type, false); + column.set_name(std::move(name)); + column.set_is_key(is_key); + if (!default_value.empty()) { + column.set_default_value(default_value); + } + return column; +} + +TEST(PartialUpdateInfoTest, MaterializesTimestampNsCurrentTimestampDefaults) { + TabletSchema schema; + schema.append_column(make_column("id", FieldType::OLAP_FIELD_TYPE_INT, true)); + schema.append_column(make_column("ts0", FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS, false, + "CURRENT_TIMESTAMP")); + schema.append_column(make_column("ts6", FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS, false, + "CURRENT_TIMESTAMP(6)")); + schema.append_column(make_column("ts7", FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS, false, + "CURRENT_TIMESTAMP(7)")); + schema.append_column(make_column("ts8", FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS, false, + "CURRENT_TIMESTAMP(8)")); + schema.append_column(make_column("ts9", FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS, false, + "CURRENT_TIMESTAMP(9)")); + + PartialUpdateInfo utc_info; + ASSERT_TRUE(utc_info.init(1, 2, schema, UniqueKeyUpdateModePB::UPDATE_FIXED_COLUMNS, + PartialUpdateNewRowPolicyPB::APPEND, {"id"}, false, 1704164645000, + 123456789, "UTC", "") + .ok()); + EXPECT_EQ(utc_info.default_values, + (std::vector { + "2024-01-02 03:04:05.000000000", "2024-01-02 03:04:05.123456000", + "2024-01-02 03:04:05.123456700", "2024-01-02 03:04:05.123456780", + "2024-01-02 03:04:05.123456789"})); + + PartialUpdateInfo shanghai_info; + ASSERT_TRUE(shanghai_info + .init(1, 3, schema, UniqueKeyUpdateModePB::UPDATE_FIXED_COLUMNS, + PartialUpdateNewRowPolicyPB::APPEND, {"id"}, false, 1704164645000, + 123456789, "+08:00", "") + .ok()); + EXPECT_EQ(shanghai_info.default_values.back(), "2024-01-02 11:04:05.123456789"); +} + +} // namespace +} // namespace doris diff --git a/be/test/storage/predicate/block_column_predicate_test.cpp b/be/test/storage/predicate/block_column_predicate_test.cpp index 64d9fb244d6a7d..b06d188c8b55f7 100644 --- a/be/test/storage/predicate/block_column_predicate_test.cpp +++ b/be/test/storage/predicate/block_column_predicate_test.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -1367,6 +1368,31 @@ TEST_F(BlockColumnPredicateTest, test_timestamptz_zonemap_index) { } } +TEST_F(BlockColumnPredicateTest, test_timestamp_ns_zonemap_predicates) { + const TimeStampNsValue minimum(-1); + const TimeStampNsValue middle(0); + const TimeStampNsValue maximum(1); + segment_v2::ZoneMap zone_map_info {.min_value = Field::create_field(minimum), + .max_value = Field::create_field(maximum), + .has_null = false, + .has_not_null = true}; + + single_column_predicate_test_func( + zone_map_info, Field::create_field(middle), true); + single_column_predicate_test_func( + zone_map_info, Field::create_field(TimeStampNsValue(-2)), false); + single_column_predicate_test_func( + zone_map_info, Field::create_field(middle), true); + single_column_predicate_test_func( + zone_map_info, Field::create_field(minimum), false); + single_column_predicate_test_func( + zone_map_info, Field::create_field(minimum), true); + single_column_predicate_test_func( + zone_map_info, Field::create_field(maximum), false); + single_column_predicate_test_func( + zone_map_info, Field::create_field(maximum), true); +} + template void single_column_predicate_test_func(const segment_v2::BloomFilter* bf, Field&& check_value, bool expect_match) { @@ -1411,14 +1437,14 @@ TEST_F(BlockColumnPredicateTest, test_timestamptz_bloom_filter) { bf.get(), Field::create_field(v), true); } { - auto str = "0000-01-01 00:00:00"; + const auto* str = "0000-01-01 00:00:00"; TimestampTzValue tz {}; EXPECT_TRUE(tz.from_string(StringRef {str}, &time_zone, params, 0)); single_column_predicate_test_func( bf.get(), Field::create_field(tz), false); } { - auto str = "9999-12-31 23:59:59.999999"; + const auto* str = "9999-12-31 23:59:59.999999"; TimestampTzValue tz {}; EXPECT_TRUE(tz.from_string(StringRef {str}, &time_zone, params, 6)); single_column_predicate_test_func( @@ -1426,6 +1452,28 @@ TEST_F(BlockColumnPredicateTest, test_timestamptz_bloom_filter) { } } +TEST_F(BlockColumnPredicateTest, test_timestamp_ns_bloom_filter_predicate) { + const std::array values = { + TimeStampNsValue(std::numeric_limits::min()), TimeStampNsValue(-1), + TimeStampNsValue(0), TimeStampNsValue(1), + TimeStampNsValue(std::numeric_limits::max())}; + + std::unique_ptr bloom_filter; + EXPECT_TRUE(BloomFilter::create(BLOCK_BLOOM_FILTER, &bloom_filter)); + ASSERT_NE(bloom_filter, nullptr); + EXPECT_TRUE(bloom_filter->init(1024, 0.05, HASH_MURMUR3_X64_64)); + for (const auto& value : values) { + bloom_filter->add_bytes(reinterpret_cast(&value), sizeof(value)); + } + + for (const auto& value : values) { + single_column_predicate_test_func( + bloom_filter.get(), Field::create_field(value), true); + } + single_column_predicate_test_func( + bloom_filter.get(), Field::create_field(TimeStampNsValue(2)), false); +} + TEST_F(BlockColumnPredicateTest, PARQUET_COMPARISON_PREDICATE) { { // INT {// EQ diff --git a/be/test/storage/segment/bloom_filter_index_reader_writer_test.cpp b/be/test/storage/segment/bloom_filter_index_reader_writer_test.cpp index 17eeac11a7db15..1363234aff50dc 100644 --- a/be/test/storage/segment/bloom_filter_index_reader_writer_test.cpp +++ b/be/test/storage/segment/bloom_filter_index_reader_writer_test.cpp @@ -476,6 +476,21 @@ TEST_F(BloomFilterIndexReaderWriterTest, test_datetimev2) { delete[] val; } +TEST_F(BloomFilterIndexReaderWriterTest, test_timestamp_ns_write_read_filter) { + size_t num = 1024 * 3; + std::vector values(num); + for (size_t i = 0; i < num; ++i) { + values[i] = -1'000'000'000 + static_cast(i); + } + + const std::string file_name = "bloom_filter_timestamp_ns"; + int64_t not_exist_value = -1'000'000'001; + auto st = + test_bloom_filter_index_reader_writer_template( + file_name, values.data(), num, 1, ¬_exist_value); + EXPECT_TRUE(st.ok()); +} + TEST_F(BloomFilterIndexReaderWriterTest, test_timestamptz) { size_t num = 1024 * 3; auto base_dt = make_timestamptz(2025, 11, 14, 14, 37, 30, 999998); diff --git a/be/test/storage/segment/inverted_index_writer_test.cpp b/be/test/storage/segment/inverted_index_writer_test.cpp index 8b7f56221cf8cf..001369c2b1f2d6 100644 --- a/be/test/storage/segment/inverted_index_writer_test.cpp +++ b/be/test/storage/segment/inverted_index_writer_test.cpp @@ -35,6 +35,7 @@ #include "core/data_type/data_type_factory.hpp" #include "core/data_type/data_type_number.h" #include "core/field.h" +#include "core/value/timestamp_ns_value.h" #include "io/fs/local_file_system.h" #include "runtime/runtime_state.h" #include "storage/index/index_file_reader.h" @@ -153,8 +154,19 @@ class InvertedIndexWriterTest : public testing::Test { _CLLDELETE(r); } + template + Field create_bkd_query_field(StorageType value) { + if constexpr (primitive_type == TYPE_TIMESTAMP_NS) { + return Field::create_field(TimeStampNsValue(value)); + } else { + return Field::create_field(value); + } + } + + template void check_bkd_index(std::string index_prefix, const TabletIndex* index_meta, - const std::vector& values, const std::vector& doc_ids) { + const std::string& column_name, const std::vector& values, + const std::vector& doc_ids, StorageType range_value) { OlapReaderStatistics stats; RuntimeState runtime_state; TQueryOptions query_options; @@ -178,8 +190,8 @@ class InvertedIndexWriterTest : public testing::Test { context->stats = &stats; context->runtime_state = &runtime_state; - Field qp = Field::create_field(values[i]); - auto status = bkd_reader->query(context, "c1", qp, + Field qp = create_bkd_query_field(values[i]); + auto status = bkd_reader->query(context, column_name, qp, doris::segment_v2::InvertedIndexQueryType::EQUAL_QUERY, bitmap); EXPECT_TRUE(status.ok()) << status; @@ -200,44 +212,43 @@ class InvertedIndexWriterTest : public testing::Test { // Test range queries // Test LESS_THAN query std::shared_ptr less_than_bitmap = std::make_shared(); - int32_t test_value = 200; auto context = std::make_shared(); context->stats = &stats; context->runtime_state = &runtime_state; - Field test_qp = Field::create_field(test_value); - auto status = bkd_reader->query(context, "c1", test_qp, + Field test_qp = create_bkd_query_field(range_value); + auto status = bkd_reader->query(context, column_name, test_qp, doris::segment_v2::InvertedIndexQueryType::LESS_THAN_QUERY, less_than_bitmap); EXPECT_TRUE(status.ok()) << status; // Verify documents with values less than test_value are in the result for (size_t i = 0; i < values.size(); i++) { - if (values[i] < test_value) { + if (values[i] < range_value) { EXPECT_TRUE(less_than_bitmap->contains(doc_ids[i])) - << "Value " << values[i] << " should be less than " << test_value; + << "Value " << values[i] << " should be less than " << range_value; } else { EXPECT_FALSE(less_than_bitmap->contains(doc_ids[i])) - << "Value " << values[i] << " should not be less than " << test_value; + << "Value " << values[i] << " should not be less than " << range_value; } } // Test GREATER_THAN query std::shared_ptr greater_than_bitmap = std::make_shared(); - status = bkd_reader->query(context, "c1", test_qp, + status = bkd_reader->query(context, column_name, test_qp, doris::segment_v2::InvertedIndexQueryType::GREATER_THAN_QUERY, greater_than_bitmap); EXPECT_TRUE(status.ok()) << status; // Verify documents with values greater than test_value are in the result for (size_t i = 0; i < values.size(); i++) { - if (values[i] > test_value) { + if (values[i] > range_value) { EXPECT_TRUE(greater_than_bitmap->contains(doc_ids[i])) - << "Value " << values[i] << " should be greater than " << test_value; + << "Value " << values[i] << " should be greater than " << range_value; } else { EXPECT_FALSE(greater_than_bitmap->contains(doc_ids[i])) - << "Value " << values[i] << " should not be greater than " << test_value; + << "Value " << values[i] << " should not be greater than " << range_value; } } } @@ -628,7 +639,7 @@ class InvertedIndexWriterTest : public testing::Test { std::vector doc_ids = {0, 1, 2, 3, 4}; // Verify the BKD index using the appropriate method - check_bkd_index(index_path_prefix, &idx_meta, values, doc_ids); + check_bkd_index(index_path_prefix, &idx_meta, "c1", values, doc_ids, 200); } void test_unicode_string_write(std::string_view rowset_id, int seg_id, @@ -790,6 +801,48 @@ TEST_F(InvertedIndexWriterTest, NumericWrite) { test_numeric_write("test_rowset_3", 0); } +TEST_F(InvertedIndexWriterTest, TimeStampNsWriteReadFilter) { + TabletColumn field; + field.set_name("dt"); + field.set_unique_id(0); + field.set_type(FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS); + field.set_is_nullable(false); + + TabletIndexPB index_meta_pb; + index_meta_pb.set_index_type(IndexType::INVERTED); + index_meta_pb.set_index_id(1); + index_meta_pb.set_index_name("test_timestamp_ns"); + index_meta_pb.add_col_unique_id(0); + TabletIndex index_meta; + index_meta.init_from_pb(index_meta_pb); + + const std::string rowset_id = "test_timestamp_ns"; + const std::string index_path_prefix {InvertedIndexDescriptor::get_index_file_path_prefix( + local_segment_path(kTestDir, rowset_id, 0))}; + const std::string index_path = + InvertedIndexDescriptor::get_index_file_path_v2(index_path_prefix); + io::FileWriterPtr file_writer; + ASSERT_TRUE(io::global_local_filesystem()->create_file(index_path, &file_writer).ok()); + auto index_file_writer = std::make_unique( + io::global_local_filesystem(), index_path_prefix, rowset_id, 0, + InvertedIndexStorageFormatPB::V2, std::move(file_writer)); + + std::unique_ptr column_writer; + ASSERT_TRUE( + IndexColumnWriter::create(&field, &column_writer, index_file_writer.get(), &index_meta) + .ok()); + const std::vector values = {std::numeric_limits::min(), -1, 0, 1, + std::numeric_limits::max()}; + ASSERT_TRUE(column_writer->add_values("dt", values.data(), values.size()).ok()); + ASSERT_TRUE(column_writer->finish().ok()); + ASSERT_TRUE(index_file_writer->begin_close().ok()); + ASSERT_TRUE(index_file_writer->finish_close().ok()); + + const std::vector doc_ids = {0, 1, 2, 3, 4}; + check_bkd_index(index_path_prefix, &index_meta, "dt", values, doc_ids, + int64_t {0}); +} + // Test case for Unicode string values with enable_correct_term_write=true TEST_F(InvertedIndexWriterTest, UnicodeStringWriteEnabled) { test_unicode_string_write("test_rowset_4", 0, true); @@ -1544,4 +1597,4 @@ TEST_F(InvertedIndexWriterTest, NormsFileCreationWithTokenization) { << "inverted_index_writer.cpp where .nrm file creation depends on _should_analyzer."; } -} // namespace doris::segment_v2 \ No newline at end of file +} // namespace doris::segment_v2 diff --git a/be/test/storage/segment/variant_assembler_legacy_test.cpp b/be/test/storage/segment/variant_assembler_legacy_test.cpp index 9dff7d24189ad1..f77516e9fa3d6d 100644 --- a/be/test/storage/segment/variant_assembler_legacy_test.cpp +++ b/be/test/storage/segment/variant_assembler_legacy_test.cpp @@ -41,6 +41,7 @@ #include "core/data_type/data_type_nullable.h" #include "core/value/decimalv2_value.h" #include "core/value/jsonb_value.h" +#include "core/value/timestamp_ns_value.h" #include "core/value/timestamptz_value.h" #include "exprs/function/parse/variant_string_parse.h" #include "storage/segment/variant/v2/variant_assembler.h" @@ -350,6 +351,12 @@ TEST(VariantAssemblerLegacyTest, BinaryExtractScalarTypeMatrixPreservesTypedStat TYPE_TIMESTAMPTZ, {R"("1970-01-01 00:00:01.000000+00:00")", R"("1970-01-01 00:00:02.000000+00:00")"}); + expect_typed_cells( + {scaled_storage_cell(FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS, 9, -1), + scaled_storage_cell(FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS, 9, 123456789)}, + TYPE_TIMESTAMP_NS, + {R"("1969-12-31 23:59:59.999999999")", R"("1970-01-01 00:00:00.123456789")"}); + expect_typed_cells( {decimal_storage_cell(FieldType::OLAP_FIELD_TYPE_DECIMAL32, 9, 2, 1234), decimal_storage_cell(FieldType::OLAP_FIELD_TYPE_DECIMAL32, 9, 2, -5678)}, diff --git a/be/test/storage/segment/zone_map_index_test.cpp b/be/test/storage/segment/zone_map_index_test.cpp index db4b692b1f1477..57bfecd8552f15 100644 --- a/be/test/storage/segment/zone_map_index_test.cpp +++ b/be/test/storage/segment/zone_map_index_test.cpp @@ -1119,6 +1119,71 @@ TEST_F(ColumnZoneMapTest, TimestamptzPage) { EXPECT_EQ(false, zone_maps[4].has_not_null()); } +TEST_F(ColumnZoneMapTest, TimeStampNsWriteReadFilter) { + auto column = std::make_shared(); + column->_unique_id = 0; + column->_col_name = "timestamp_ns"; + column->_type = FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS; + column->_is_key = true; + column->_is_nullable = true; + column->_length = 8; + column->_index_length = 8; + + auto data_type = DataTypeFactory::instance().create_data_type(TYPE_TIMESTAMP_NS, false, 0, 9); + std::unique_ptr writer; + ASSERT_TRUE(ZoneMapIndexWriter::create(data_type, column.get(), writer).ok()); + + TimeStampNsValue values[] = { + TimeStampNsValue(std::numeric_limits::min()), + TimeStampNsValue(-1), + TimeStampNsValue(0), + TimeStampNsValue(std::numeric_limits::max()), + }; + writer->add_values(values, 2); + ASSERT_TRUE(writer->flush().ok()); + writer->add_values(values + 2, 2); + ASSERT_TRUE(writer->flush().ok()); + + const std::string file_path = kTestDir + "/timestamp_ns_zonemap"; + io::FileWriterPtr file_writer; + ASSERT_TRUE(_fs->create_file(file_path, &file_writer).ok()); + ColumnIndexMetaPB index_meta; + ASSERT_TRUE(writer->finish(file_writer.get(), &index_meta).ok()); + ASSERT_TRUE(file_writer->close().ok()); + + ZoneMap segment_zone_map; + ASSERT_TRUE(ZoneMap::from_proto(index_meta.zone_map_index().segment_zone_map(), data_type, + segment_zone_map) + .ok()); + EXPECT_EQ(segment_zone_map.min_value.get(), values[0]); + EXPECT_EQ(segment_zone_map.max_value.get(), values[3]); + + io::FileReaderSPtr file_reader; + ASSERT_TRUE(_fs->open_file(file_path, &file_reader).ok()); + ZoneMapIndexReader zone_map_reader(file_reader, index_meta.zone_map_index().page_zone_maps()); + ASSERT_TRUE(zone_map_reader.load(true, false).ok()); + ASSERT_EQ(zone_map_reader.num_pages(), 2); + + ZoneMap negative_page_zone_map; + ASSERT_TRUE(ZoneMap::from_proto(zone_map_reader.page_zone_maps()[0], data_type, + negative_page_zone_map) + .ok()); + EXPECT_EQ(negative_page_zone_map.min_value.get(), values[0]); + EXPECT_EQ(negative_page_zone_map.max_value.get(), values[1]); + + ZoneMap nonnegative_page_zone_map; + ASSERT_TRUE(ZoneMap::from_proto(zone_map_reader.page_zone_maps()[1], data_type, + nonnegative_page_zone_map) + .ok()); + EXPECT_EQ(nonnegative_page_zone_map.min_value.get(), values[2]); + EXPECT_EQ(nonnegative_page_zone_map.max_value.get(), values[3]); + + const auto epoch = Field::create_field(TimeStampNsValue(0)); + ComparisonPredicateBase epoch_predicate(0, "", epoch); + EXPECT_FALSE(epoch_predicate.evaluate_and(negative_page_zone_map)); + EXPECT_TRUE(epoch_predicate.evaluate_and(nonnegative_page_zone_map)); +} + // Regression test for "all-null page after a value page" — int variant. // // Page 1 has integers, page 2 is all nulls. The fix in flush() guards the diff --git a/be/test/storage/tablet/tablet_schema_test.cpp b/be/test/storage/tablet/tablet_schema_test.cpp index e39c1733444453..ef46612e38dd7f 100644 --- a/be/test/storage/tablet/tablet_schema_test.cpp +++ b/be/test/storage/tablet/tablet_schema_test.cpp @@ -107,6 +107,25 @@ TEST_F(TabletSchemaTest, test_tablet_column_init_from_pb) { EXPECT_TRUE(tablet_column.variant_enable_typed_paths_to_sparse()); } +TEST_F(TabletSchemaTest, test_tablet_column_type_does_not_depend_on_frac) { + ColumnPB column_pb; + column_pb.set_name("datetime_v2_column"); + column_pb.set_type("DATETIMEV2"); + column_pb.set_frac(9); + + TabletColumn tablet_column; + tablet_column.init_from_pb(column_pb); + + // The protobuf type is authoritative. An invalid DATETIMEV2 scale must be rejected by type + // validation instead of silently changing the column's physical representation. + EXPECT_EQ(FieldType::OLAP_FIELD_TYPE_DATETIMEV2, tablet_column.type()); + EXPECT_EQ(9, tablet_column.frac()); + + column_pb.set_type("TIMESTAMP_NS"); + tablet_column.init_from_pb(column_pb); + EXPECT_EQ(FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS, tablet_column.type()); +} + TEST_F(TabletSchemaTest, test_tablet_column_init_from_thrift) { TColumn tcolumn; tcolumn.__set_column_name("thrift_column"); diff --git a/be/test/storage/variant/variant_column_writer_reader_test.cpp b/be/test/storage/variant/variant_column_writer_reader_test.cpp index 6ed78e24324ea9..196266754954f0 100644 --- a/be/test/storage/variant/variant_column_writer_reader_test.cpp +++ b/be/test/storage/variant/variant_column_writer_reader_test.cpp @@ -36,6 +36,7 @@ #include "core/data_type/data_type_map.h" #include "core/data_type/data_type_number.h" #include "core/data_type/data_type_string.h" +#include "core/data_type/data_type_timestamp_ns.h" #include "core/data_type/data_type_variant.h" #include "core/data_type/data_type_variant_v2.h" #include "core/data_type_serde/data_type_serde.h" @@ -300,6 +301,109 @@ TEST(VariantPathBuilderTest, PreservesIntegerWidthAcrossPromotion) { EXPECT_EQ(remove_nullable(builder.type())->get_primitive_type(), TYPE_INT); } +TEST(VariantPathBuilderTest, MaterializesTimestampNsWithoutLosingNanoseconds) { + VariantBatchBuilder value_builder; + auto before_epoch = value_builder.begin_row(); + before_epoch.add_timestamp_nanos(-1, false); + before_epoch.finish(); + auto epoch = value_builder.begin_row(); + epoch.add_timestamp_nanos(0, false); + epoch.finish(); + auto normal = value_builder.begin_row(); + normal.add_timestamp_nanos(123456789, false); + normal.finish(); + VariantBatchBuilder values = value_builder.finish_batch(); + + segment_v2::VariantPathBuilder builder(PathInData("timestamp_ns")); + ASSERT_TRUE(builder.append(values.value_at(0), 0).ok()); + ASSERT_TRUE(builder.append(values.value_at(1), 1).ok()); + ASSERT_TRUE(builder.append(values.value_at(2), 2).ok()); + ASSERT_EQ(remove_nullable(builder.type())->get_primitive_type(), TYPE_TIMESTAMP_NS); + + ColumnPtr materialized; + ASSERT_TRUE(builder.materialize(&materialized).ok()); + const auto& nullable = assert_cast(*materialized); + const auto& data = + assert_cast(nullable.get_nested_column()).get_data(); + ASSERT_EQ(data.size(), 3); + EXPECT_EQ(data[0].epoch_nanos(), -1); + EXPECT_EQ(data[1].epoch_nanos(), 0); + EXPECT_EQ(data[2].epoch_nanos(), 123456789); +} + +TEST(VariantPathBuilderTest, PromotesTimestampMicrosAndNanosInEitherOrder) { + const auto verify = [](bool nanos_first) { + VariantBatchBuilder value_builder; + auto first = value_builder.begin_row(); + if (nanos_first) { + first.add_timestamp_nanos(123456789, false); + } else { + first.add_timestamp_micros(-1, false); + } + first.finish(); + auto second = value_builder.begin_row(); + if (nanos_first) { + second.add_timestamp_micros(-1, false); + } else { + second.add_timestamp_nanos(123456789, false); + } + second.finish(); + VariantBatchBuilder values = value_builder.finish_batch(); + + segment_v2::VariantPathBuilder builder(PathInData("mixed_timestamp")); + ASSERT_TRUE(builder.append(values.value_at(0), 0).ok()); + ASSERT_TRUE(builder.append(values.value_at(1), 1).ok()); + ASSERT_EQ(remove_nullable(builder.type())->get_primitive_type(), TYPE_TIMESTAMP_NS); + + ColumnPtr materialized; + ASSERT_TRUE(builder.materialize(&materialized).ok()); + const auto& nullable = assert_cast(*materialized); + const auto& data = + assert_cast(nullable.get_nested_column()).get_data(); + ASSERT_EQ(data.size(), 2); + EXPECT_EQ(data[nanos_first ? 0 : 1].epoch_nanos(), 123456789); + EXPECT_EQ(data[nanos_first ? 1 : 0].epoch_nanos(), -1000); + }; + + verify(false); + verify(true); +} + +TEST(VariantPathBuilderTest, PreservesOutOfRangeTimestampWhenPromotingToNanos) { + const auto verify = [](bool nanos_first) { + VariantBatchBuilder value_builder; + const auto append = [&](bool nanos) { + auto row = value_builder.begin_row(); + if (nanos) { + row.add_timestamp_nanos(123456789, false); + } else { + // 2500-01-01 is valid for DATETIMEV2 but outside TIMESTAMP_NS's Int64 range. + row.add_timestamp_micros(16725225600000000, false); + } + row.finish(); + }; + append(nanos_first); + append(!nanos_first); + VariantBatchBuilder values = value_builder.finish_batch(); + + segment_v2::VariantPathBuilder builder(PathInData("mixed_timestamp")); + ASSERT_TRUE(builder.append(values.value_at(0), 0).ok()); + ASSERT_TRUE(builder.append(values.value_at(1), 1).ok()); + EXPECT_EQ(remove_nullable(builder.type())->get_primitive_type(), TYPE_JSONB); + EXPECT_EQ(builder.non_null_rows(), 2); + + ColumnPtr materialized; + ASSERT_TRUE(builder.materialize(&materialized).ok()); + const auto& nullable = assert_cast(*materialized); + ASSERT_EQ(nullable.size(), 2); + EXPECT_FALSE(nullable.is_null_at(0)); + EXPECT_FALSE(nullable.is_null_at(1)); + }; + + verify(false); + verify(true); +} + TEST(VariantPathBuilderTest, PromotesCompatibleDecimalScalesInEitherOrderAndInsideArrays) { const auto verify = [](bool reverse, bool array) { VariantBatchBuilder value_builder; diff --git a/be/test/testutil/datetime_ut_util.h b/be/test/testutil/datetime_ut_util.h index 9f0967ce1d76dc..ff6de97dd21186 100644 --- a/be/test/testutil/datetime_ut_util.h +++ b/be/test/testutil/datetime_ut_util.h @@ -34,4 +34,4 @@ inline auto make_timestamptz(int year, int month, int day, int hour, int minute, return TimestampTzValue(dt.to_date_int_val()); } -} // namespace doris \ No newline at end of file +} // namespace doris diff --git a/fe/be-java-extensions/java-common/src/main/java/org/apache/doris/common/jni/utils/JavaUdfDataType.java b/fe/be-java-extensions/java-common/src/main/java/org/apache/doris/common/jni/utils/JavaUdfDataType.java index 7df4ca36119fc4..72f170f3a01fde 100644 --- a/fe/be-java-extensions/java-common/src/main/java/org/apache/doris/common/jni/utils/JavaUdfDataType.java +++ b/fe/be-java-extensions/java-common/src/main/java/org/apache/doris/common/jni/utils/JavaUdfDataType.java @@ -50,6 +50,8 @@ public class JavaUdfDataType { public static final JavaUdfDataType DATEV2 = new JavaUdfDataType("DATEV2", TPrimitiveType.DATEV2, 4); public static final JavaUdfDataType DATETIMEV2 = new JavaUdfDataType("DATETIMEV2", TPrimitiveType.DATETIMEV2, 8); + public static final JavaUdfDataType TIMESTAMP_NS = new JavaUdfDataType("TIMESTAMP_NS", + TPrimitiveType.TIMESTAMP_NS, 8); public static final JavaUdfDataType DECIMAL32 = new JavaUdfDataType("DECIMAL32", TPrimitiveType.DECIMAL32, 4); public static final JavaUdfDataType DECIMAL64 = new JavaUdfDataType("DECIMAL64", TPrimitiveType.DECIMAL64, 8); public static final JavaUdfDataType DECIMAL128 = new JavaUdfDataType("DECIMAL128", TPrimitiveType.DECIMAL128I, @@ -85,6 +87,7 @@ public static void addJavaUdfDataType(JavaUdfDataType dataType) { addJavaUdfDataType(DECIMALV2); addJavaUdfDataType(DATEV2); addJavaUdfDataType(DATETIMEV2); + addJavaUdfDataType(TIMESTAMP_NS); addJavaUdfDataType(DECIMAL32); addJavaUdfDataType(DECIMAL64); addJavaUdfDataType(DECIMAL128); @@ -151,7 +154,8 @@ public static Set getCandidateTypes(Class c) { } else if (Type.DATE_SUPPORTED_JAVA_TYPE.contains(c)) { return Sets.newHashSet(JavaUdfDataType.DATE, JavaUdfDataType.DATEV2); } else if (Type.DATETIME_SUPPORTED_JAVA_TYPE.contains(c)) { - return Sets.newHashSet(JavaUdfDataType.DATETIME, JavaUdfDataType.DATETIMEV2); + return Sets.newHashSet(JavaUdfDataType.DATETIME, JavaUdfDataType.DATETIMEV2, + JavaUdfDataType.TIMESTAMP_NS); } else if (c == BigInteger.class) { return Sets.newHashSet(JavaUdfDataType.LARGEINT); } else if (c == BigDecimal.class) { diff --git a/fe/be-java-extensions/java-common/src/main/java/org/apache/doris/common/jni/utils/TypeNativeBytes.java b/fe/be-java-extensions/java-common/src/main/java/org/apache/doris/common/jni/utils/TypeNativeBytes.java index 7474ce4467d31f..81a9f6f652a6d3 100644 --- a/fe/be-java-extensions/java-common/src/main/java/org/apache/doris/common/jni/utils/TypeNativeBytes.java +++ b/fe/be-java-extensions/java-common/src/main/java/org/apache/doris/common/jni/utils/TypeNativeBytes.java @@ -25,6 +25,7 @@ import java.time.DateTimeException; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.ZoneOffset; import java.util.Arrays; public class TypeNativeBytes { @@ -291,4 +292,35 @@ public static Object convertToJavaDateTimeV2(long time, Class clz) { return null; } } + + public static long convertToTimestampNs(LocalDateTime value) { + long epochSeconds = value.toEpochSecond(ZoneOffset.UTC); + if (epochSeconds < 0) { + // Keep the intermediate product in range for values in the first second + // representable by a signed 64-bit nanosecond timestamp. + return Math.addExact(Math.multiplyExact(epochSeconds + 1, 1_000_000_000L), + value.getNano() - 1_000_000_000L); + } + return Math.addExact(Math.multiplyExact(epochSeconds, 1_000_000_000L), value.getNano()); + } + + public static LocalDateTime convertToJavaTimestampNs(long epochNanos) { + long epochSeconds = Math.floorDiv(epochNanos, 1_000_000_000L); + int nanosOfSecond = (int) Math.floorMod(epochNanos, 1_000_000_000L); + return LocalDateTime.ofEpochSecond(epochSeconds, nanosOfSecond, ZoneOffset.UTC); + } + + public static Object convertToJavaTimestampNs(long epochNanos, Class clz) { + LocalDateTime value = convertToJavaTimestampNs(epochNanos); + if (LocalDateTime.class.equals(clz)) { + return value; + } else if (org.joda.time.DateTime.class.equals(clz)) { + return new org.joda.time.DateTime(value.getYear(), value.getMonthValue(), value.getDayOfMonth(), + value.getHour(), value.getMinute(), value.getSecond(), value.getNano() / 1_000_000); + } else if (org.joda.time.LocalDateTime.class.equals(clz)) { + return new org.joda.time.LocalDateTime(value.getYear(), value.getMonthValue(), value.getDayOfMonth(), + value.getHour(), value.getMinute(), value.getSecond(), value.getNano() / 1_000_000); + } + return null; + } } diff --git a/fe/be-java-extensions/java-common/src/main/java/org/apache/doris/common/jni/vec/ColumnType.java b/fe/be-java-extensions/java-common/src/main/java/org/apache/doris/common/jni/vec/ColumnType.java index 983681d24dcb72..b0e5547008709b 100644 --- a/fe/be-java-extensions/java-common/src/main/java/org/apache/doris/common/jni/vec/ColumnType.java +++ b/fe/be-java-extensions/java-common/src/main/java/org/apache/doris/common/jni/vec/ColumnType.java @@ -51,6 +51,7 @@ public enum Type { DATEV2(4), DATETIME(8), DATETIMEV2(8), + TIMESTAMP_NS(8), TIMESTAMPTZ(8), CHAR(-1), VARCHAR(-1), @@ -193,6 +194,10 @@ public boolean isDateTimeV2() { return type == Type.DATETIMEV2; } + public boolean isTimestampNs() { + return type == Type.TIMESTAMP_NS; + } + public boolean isPrimitive() { return type == Type.BOOLEAN || type == Type.BYTE || type == Type.TINYINT || type == Type.SMALLINT || type == Type.INT || type == Type.BIGINT || type == Type.FLOAT || type == Type.DOUBLE @@ -334,6 +339,10 @@ private static ColumnType parseType(String columnName, String hiveType, boolean case "datetimev1": type = Type.DATETIME; break; + case "timestamp_ns": + type = Type.TIMESTAMP_NS; + precision = 9; + break; case "binary": case "bytes": type = Type.BINARY; diff --git a/fe/be-java-extensions/java-common/src/main/java/org/apache/doris/common/jni/vec/VectorColumn.java b/fe/be-java-extensions/java-common/src/main/java/org/apache/doris/common/jni/vec/VectorColumn.java index 36d2329da89976..224d9426d0a7f2 100644 --- a/fe/be-java-extensions/java-common/src/main/java/org/apache/doris/common/jni/vec/VectorColumn.java +++ b/fe/be-java-extensions/java-common/src/main/java/org/apache/doris/common/jni/vec/VectorColumn.java @@ -447,6 +447,8 @@ public int appendNull(ColumnType.Type typeValue) { case DATETIME: case DATETIMEV2: return appendDateTime(LocalDateTime.MIN); + case TIMESTAMP_NS: + return appendDateTime(LocalDateTime.of(1970, 1, 1, 0, 0)); case TIMESTAMPTZ: return appendTimeStampTz(LocalDateTime.MIN); case CHAR: @@ -1112,7 +1114,11 @@ public void appendDateTime(LocalDateTime[] batch, boolean isNullable) { for (LocalDateTime v : batch) { if (v == null) { putNull(appendIndex); - putDateTime(appendIndex, LocalDateTime.MIN); + if (columnType.isTimestampNs()) { + putDateTime(appendIndex, LocalDateTime.of(1970, 1, 1, 0, 0)); + } else { + putDateTime(appendIndex, LocalDateTime.MIN); + } } else { putDateTime(appendIndex, v); } @@ -1122,7 +1128,9 @@ public void appendDateTime(LocalDateTime[] batch, boolean isNullable) { public LocalDateTime getDateTime(int rowId) { long time = OffHeap.getLong(null, data + rowId * 8L); - if (columnType.isDateTimeV2()) { + if (columnType.isTimestampNs()) { + return TypeNativeBytes.convertToJavaTimestampNs(time); + } else if (columnType.isDateTimeV2()) { return TypeNativeBytes.convertToJavaDateTimeV2(time); } else { return TypeNativeBytes.convertToJavaDateTimeV1(time); @@ -1144,7 +1152,9 @@ public Object[] getDateTimeColumn(int start, int end, Class clz) { for (int i = start; i < end; ++i) { if (!isNullAt(i)) { long time = OffHeap.getLong(null, data + i * 8L); - if (columnType.isDateTimeV2()) { + if (columnType.isTimestampNs()) { + result[i - start] = TypeNativeBytes.convertToJavaTimestampNs(time, clz); + } else if (columnType.isDateTimeV2()) { result[i - start] = TypeNativeBytes.convertToJavaDateTimeV2(time, clz); } else { result[i - start] = TypeNativeBytes.convertToJavaDateTimeV1(time, clz); @@ -1156,7 +1166,9 @@ public Object[] getDateTimeColumn(int start, int end, Class clz) { private void putDateTime(int rowId, LocalDateTime v) { long time; - if (columnType.isDateTimeV2()) { + if (columnType.isTimestampNs()) { + time = TypeNativeBytes.convertToTimestampNs(v); + } else if (columnType.isDateTimeV2()) { time = TypeNativeBytes.convertToDateTimeV2(v.getYear(), v.getMonthValue(), v.getDayOfMonth(), v.getHour(), v.getMinute(), v.getSecond(), v.getNano() / 1000); } else { @@ -1683,6 +1695,7 @@ public Object[] newObjectContainerArray(ColumnType.Type type, int size) { return new LocalDate[size]; case DATETIME: case DATETIMEV2: + case TIMESTAMP_NS: return new LocalDateTime[size]; case TIMESTAMPTZ: // MAYBE use LocalDateTime is not appropriate @@ -1745,6 +1758,7 @@ public void appendObjectColumn(Object[] batch, boolean isNullable) { break; case DATETIME: case DATETIMEV2: + case TIMESTAMP_NS: appendDateTime((LocalDateTime[]) batch, isNullable); break; case TIMESTAMPTZ: @@ -1814,6 +1828,7 @@ public Object[] getObjectColumn(int start, int end) { return getDateColumn(start, end); case DATETIME: case DATETIMEV2: + case TIMESTAMP_NS: return getDateTimeColumn(start, end); case TIMESTAMPTZ: return getTimeStampTzColumn(start, end); @@ -1879,6 +1894,7 @@ public void appendValue(ColumnValue o) { break; case DATETIME: case DATETIMEV2: + case TIMESTAMP_NS: appendDateTime(o.getDateTime()); break; case TIMESTAMPTZ: @@ -1973,6 +1989,7 @@ public void dump(StringBuilder sb, int i) { break; case DATETIME: case DATETIMEV2: + case TIMESTAMP_NS: sb.append(getDateTime(i)); break; case TIMESTAMPTZ: diff --git a/fe/be-java-extensions/java-common/src/test/java/org/apache/doris/common/jni/JniScannerTest.java b/fe/be-java-extensions/java-common/src/test/java/org/apache/doris/common/jni/JniScannerTest.java index 9e9b15fc510c38..182b5f58330117 100644 --- a/fe/be-java-extensions/java-common/src/test/java/org/apache/doris/common/jni/JniScannerTest.java +++ b/fe/be-java-extensions/java-common/src/test/java/org/apache/doris/common/jni/JniScannerTest.java @@ -19,6 +19,7 @@ import org.apache.doris.common.jni.utils.OffHeap; +import org.apache.doris.common.jni.utils.TypeNativeBytes; import org.apache.doris.common.jni.vec.ColumnType; import org.apache.doris.common.jni.vec.VectorTable; @@ -26,10 +27,40 @@ import org.junit.Test; import java.io.IOException; +import java.time.LocalDateTime; import java.util.Arrays; import java.util.HashMap; public class JniScannerTest { + @Test + public void testTimestampNsVectorRoundTrip() { + OffHeap.setTesting(); + LocalDateTime minimum = LocalDateTime.parse("1677-09-21T00:12:43.145224192"); + LocalDateTime beforeEpoch = LocalDateTime.parse("1969-12-31T23:59:59.999999999"); + LocalDateTime epoch = LocalDateTime.parse("1970-01-01T00:00:00.000000000"); + LocalDateTime maximum = LocalDateTime.parse("2262-04-11T23:47:16.854775807"); + + Assert.assertEquals(Long.MIN_VALUE, TypeNativeBytes.convertToTimestampNs(minimum)); + Assert.assertEquals(-1, TypeNativeBytes.convertToTimestampNs(beforeEpoch)); + Assert.assertEquals(0, TypeNativeBytes.convertToTimestampNs(epoch)); + Assert.assertEquals(Long.MAX_VALUE, TypeNativeBytes.convertToTimestampNs(maximum)); + Assert.assertEquals(minimum, TypeNativeBytes.convertToJavaTimestampNs(Long.MIN_VALUE)); + Assert.assertEquals(maximum, TypeNativeBytes.convertToJavaTimestampNs(Long.MAX_VALUE)); + + ColumnType type = ColumnType.parseType("ts", "timestamp_ns"); + Assert.assertEquals(ColumnType.Type.TIMESTAMP_NS, type.getType()); + Assert.assertEquals(9, type.getPrecision()); + VectorTable table = VectorTable.createWritableTable( + new ColumnType[] {type}, new String[] {"ts"}, 5); + try { + table.appendData(0, new LocalDateTime[] {minimum, beforeEpoch, epoch, maximum, null}, true); + Assert.assertArrayEquals(new LocalDateTime[] {minimum, beforeEpoch, epoch, maximum, null}, + table.getMaterializedData()[0]); + } finally { + table.close(); + } + } + @Test public void testUnencodedStructFieldNamesRemainLowerCase() { ColumnType structType = ColumnType.parseType( diff --git a/fe/be-java-extensions/java-udf/src/main/java/org/apache/doris/udf/BaseExecutor.java b/fe/be-java-extensions/java-udf/src/main/java/org/apache/doris/udf/BaseExecutor.java index 6356576baaf573..a1f9af5eceff91 100644 --- a/fe/be-java-extensions/java-udf/src/main/java/org/apache/doris/udf/BaseExecutor.java +++ b/fe/be-java-extensions/java-udf/src/main/java/org/apache/doris/udf/BaseExecutor.java @@ -234,7 +234,8 @@ protected ColumnValueConverter getInputConverter(TPrimitiveType primitiveType, C break; } case DATETIME: - case DATETIMEV2: { + case DATETIMEV2: + case TIMESTAMP_NS: { if (org.joda.time.DateTime.class.equals(clz)) { return (Object[] columnData) -> { Object[] result = new org.joda.time.DateTime[columnData.length]; @@ -343,7 +344,8 @@ protected ColumnValueConverter getOutputConverter(JavaUdfDataType returnType, Cl break; } case DATETIME: - case DATETIMEV2: { + case DATETIMEV2: + case TIMESTAMP_NS: { if (org.joda.time.DateTime.class.equals(clz)) { return (Object[] columnData) -> { Object[] result = new LocalDateTime[columnData.length]; diff --git a/fe/fe-catalog/src/main/java/org/apache/doris/analysis/DateLiteral.java b/fe/fe-catalog/src/main/java/org/apache/doris/analysis/DateLiteral.java index edb4c7b3c533c1..88ec6851995cba 100644 --- a/fe/fe-catalog/src/main/java/org/apache/doris/analysis/DateLiteral.java +++ b/fe/fe-catalog/src/main/java/org/apache/doris/analysis/DateLiteral.java @@ -422,6 +422,9 @@ public int compareLiteral(LiteralExpr expr) { long diff = getMicroPartWithinScale() - other.getMicroPartWithinScale(); return diff < 0 ? -1 : (diff == 0 ? 0 : 1); } + if (expr instanceof TimeStampNsLiteral) { + return -expr.compareLiteral(this); + } // date time will not overflow when doing addition and subtraction return Integer.signum(getStringValue().compareTo(expr.getStringValue())); } diff --git a/fe/fe-catalog/src/main/java/org/apache/doris/analysis/ExprVisitor.java b/fe/fe-catalog/src/main/java/org/apache/doris/analysis/ExprVisitor.java index fbed2844989f71..2fb6d46f2bdae9 100644 --- a/fe/fe-catalog/src/main/java/org/apache/doris/analysis/ExprVisitor.java +++ b/fe/fe-catalog/src/main/java/org/apache/doris/analysis/ExprVisitor.java @@ -18,7 +18,7 @@ package org.apache.doris.analysis; /** - * Abstract visitor base class for {@link Expr} and all 39 concrete subclasses. + * Abstract visitor base class for {@link Expr} and all concrete subclasses. * Follows the same {@code } pattern as * {@code org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor}. * @@ -69,6 +69,10 @@ public R visitDateLiteral(DateLiteral expr, C context) { return visit(expr, context); } + public R visitTimeStampNsLiteral(TimeStampNsLiteral expr, C context) { + return visit(expr, context); + } + public R visitTimeV2Literal(TimeV2Literal expr, C context) { return visit(expr, context); } diff --git a/fe/fe-catalog/src/main/java/org/apache/doris/analysis/TimeStampNsLiteral.java b/fe/fe-catalog/src/main/java/org/apache/doris/analysis/TimeStampNsLiteral.java new file mode 100644 index 00000000000000..87f55aa50b4278 --- /dev/null +++ b/fe/fe-catalog/src/main/java/org/apache/doris/analysis/TimeStampNsLiteral.java @@ -0,0 +1,372 @@ +// 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. + +package org.apache.doris.analysis; + +import org.apache.doris.catalog.PrimitiveType; +import org.apache.doris.catalog.ScalarType; +import org.apache.doris.catalog.Type; +import org.apache.doris.common.AnalysisException; + +import com.google.common.base.Preconditions; +import com.google.gson.annotations.SerializedName; + +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.time.DateTimeException; +import java.time.LocalDateTime; +import java.time.Year; +import java.time.ZoneOffset; + +/** + * Legacy literal for the fixed nanosecond-precision TIMESTAMP_NS type. + * + *

TIMESTAMP_NS owns its value and range logic instead of inheriting the unrelated calendar + * encodings and microsecond rules in {@link DateLiteral}.

+ */ +public final class TimeStampNsLiteral extends LiteralExpr { + private static final long NANOSECONDS_PER_SECOND = 1_000_000_000L; + private static final long MAX_NANOSECOND = NANOSECONDS_PER_SECOND - 1; + private static final int MIN_YEAR = 1677; + private static final int MAX_YEAR = 2262; + private static final LocalDateTime MIN_VALUE + = LocalDateTime.of(MIN_YEAR, 9, 21, 0, 12, 43, 145224192); + private static final LocalDateTime MAX_VALUE + = LocalDateTime.of(MAX_YEAR, 4, 11, 23, 47, 16, 854775807); + + @SerializedName("y") + private long year; + @SerializedName("m") + private long month; + @SerializedName("d") + private long day; + @SerializedName("h") + private long hour; + @SerializedName("M") + private long minute; + @SerializedName("s") + private long second; + @SerializedName("ns") + private long nanosecond; + + public TimeStampNsLiteral() { + type = Type.TIMESTAMP_NS; + nullable = false; + } + + public TimeStampNsLiteral(boolean isMax) { + this(isMax ? MAX_VALUE : MIN_VALUE); + } + + public TimeStampNsLiteral(long year, long month, long day, long hour, long minute, long second, + long nanosecond) { + this(); + this.year = year; + this.month = month; + this.day = day; + this.hour = hour; + this.minute = minute; + this.second = second; + this.nanosecond = nanosecond; + } + + public TimeStampNsLiteral(LocalDateTime value) { + this(value.getYear(), value.getMonthValue(), value.getDayOfMonth(), value.getHour(), + value.getMinute(), value.getSecond(), value.getNano()); + } + + private TimeStampNsLiteral(TimeStampNsLiteral other) { + super(other); + year = other.year; + month = other.month; + day = other.day; + hour = other.hour; + minute = other.minute; + second = other.second; + nanosecond = other.nanosecond; + type = Type.TIMESTAMP_NS; + } + + public static TimeStampNsLiteral createMinValue() { + return new TimeStampNsLiteral(false); + } + + @Override + public Expr clone() { + return new TimeStampNsLiteral(this); + } + + @Override + public boolean isMinValue() { + return compareBoundary(MIN_VALUE) == 0; + } + + @Override + public Object getRealValue() { + LocalDateTime value = toLocalDateTime(); + return BigInteger.valueOf(value.toEpochSecond(ZoneOffset.UTC)) + .multiply(BigInteger.valueOf(NANOSECONDS_PER_SECOND)) + .add(BigInteger.valueOf(nanosecond)) + .longValueExact(); + } + + @Override + public ByteBuffer getHashValue(PrimitiveType primitiveType) { + Preconditions.checkArgument(primitiveType == PrimitiveType.TIMESTAMP_NS, + "Expected TIMESTAMP_NS hash type, but got %s", primitiveType); + ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES).order(ByteOrder.LITTLE_ENDIAN); + buffer.putLong((long) getRealValue()); + return buffer; + } + + @Override + public int compareLiteral(LiteralExpr expr) { + if (expr instanceof PlaceHolderExpr) { + return compareLiteral(((PlaceHolderExpr) expr).getLiteral()); + } + if (expr instanceof NullLiteral) { + return 1; + } + if (expr == MaxLiteral.MAX_VALUE) { + return -1; + } + if (expr instanceof TimeStampNsLiteral) { + return compareDateTime((TimeStampNsLiteral) expr); + } + if (expr instanceof DateLiteral) { + DateLiteral other = (DateLiteral) expr; + int result = compareDateTime(other.getYear(), other.getMonth(), other.getDay(), + other.getHour(), other.getMinute(), other.getSecond(), other.getMicrosecond() * 1000); + if (result == 0 && other.isDateType()) { + // DateLiteral orders DATE/DATEV2 before datetime-like literals on the same day. + // Preserve that ordering and comparison symmetry across the two literal classes. + return 1; + } + return result; + } + return Integer.signum(getStringValue().compareTo(expr.getStringValue())); + } + + private int compareDateTime(TimeStampNsLiteral other) { + return compareDateTime(other.year, other.month, other.day, other.hour, other.minute, + other.second, other.nanosecond); + } + + private int compareDateTime(long otherYear, long otherMonth, long otherDay, long otherHour, + long otherMinute, long otherSecond, long otherNanosecond) { + int result = Long.compare(year, otherYear); + if (result == 0) { + result = Long.compare(month, otherMonth); + } + if (result == 0) { + result = Long.compare(day, otherDay); + } + if (result == 0) { + result = Long.compare(hour, otherHour); + } + if (result == 0) { + result = Long.compare(minute, otherMinute); + } + if (result == 0) { + result = Long.compare(second, otherSecond); + } + if (result == 0) { + result = Long.compare(nanosecond, otherNanosecond); + } + return result; + } + + @Override + public String getStringValue() { + return String.format("%04d-%02d-%02d %02d:%02d:%02d.%09d", + year, month, day, hour, minute, second, nanosecond); + } + + public void roundFloor(int newScale) { + Preconditions.checkArgument(newScale == ScalarType.TIMESTAMP_NS_SCALE, + "TIMESTAMP_NS has fixed scale %s, but got %s", + ScalarType.TIMESTAMP_NS_SCALE, newScale); + } + + @Override + public void checkValueValid() throws AnalysisException { + if (year < MIN_YEAR || year > MAX_YEAR) { + throw new AnalysisException("TimeStampNsLiteral has invalid year value: " + year); + } + if (month < 1 || month > 12) { + throw new AnalysisException("TimeStampNsLiteral has invalid month value: " + month); + } + if (day < 1 || day > daysInMonth(year, month)) { + throw new AnalysisException("TimeStampNsLiteral has invalid day value: " + day); + } + if (hour < 0 || hour > 23) { + throw new AnalysisException("TimeStampNsLiteral has invalid hour value: " + hour); + } + if (minute < 0 || minute > 59) { + throw new AnalysisException("TimeStampNsLiteral has invalid minute value: " + minute); + } + if (second < 0 || second > 59) { + throw new AnalysisException("TimeStampNsLiteral has invalid second value: " + second); + } + if (nanosecond < 0 || nanosecond > MAX_NANOSECOND) { + throw new AnalysisException("TimeStampNsLiteral has invalid nanosecond value: " + nanosecond); + } + if (checkRange()) { + throw new AnalysisException("TimeStampNsLiteral is outside Int64 epoch nanosecond range: " + + getStringValue()); + } + } + + boolean checkRange() { + if (year < MIN_YEAR || year > MAX_YEAR || month < 1 || month > 12 + || hour < 0 || hour > 23 || minute < 0 || minute > 59 + || second < 0 || second > 59) { + return true; + } + if (day < 1 || day > daysInMonth(year, month)) { + return true; + } + if (nanosecond < 0 || nanosecond > MAX_NANOSECOND) { + return true; + } + return compareBoundary(MIN_VALUE) < 0 || compareBoundary(MAX_VALUE) > 0; + } + + private int compareBoundary(LocalDateTime boundary) { + return compareDateTime(boundary.getYear(), boundary.getMonthValue(), boundary.getDayOfMonth(), + boundary.getHour(), boundary.getMinute(), boundary.getSecond(), boundary.getNano()); + } + + private static int daysInMonth(long year, long month) { + switch ((int) month) { + case 2: + return Year.isLeap(year) ? 29 : 28; + case 4: + case 6: + case 9: + case 11: + return 30; + default: + return 31; + } + } + + public LocalDateTime toLocalDateTime() { + try { + return LocalDateTime.of((int) year, (int) month, (int) day, (int) hour, + (int) minute, (int) second, (int) nanosecond); + } catch (DateTimeException e) { + throw new IllegalStateException("Invalid TIMESTAMP_NS literal: " + getStringValue(), e); + } + } + + public TimeStampNsLiteral plusYears(long years) { + return new TimeStampNsLiteral(toLocalDateTime().plusYears(years)); + } + + public TimeStampNsLiteral plusMonths(long months) { + return new TimeStampNsLiteral(toLocalDateTime().plusMonths(months)); + } + + public TimeStampNsLiteral plusDays(long days) { + return new TimeStampNsLiteral(toLocalDateTime().plusDays(days)); + } + + public TimeStampNsLiteral plusHours(long hours) { + return new TimeStampNsLiteral(toLocalDateTime().plusHours(hours)); + } + + public TimeStampNsLiteral plusMinutes(long minutes) { + return new TimeStampNsLiteral(toLocalDateTime().plusMinutes(minutes)); + } + + public TimeStampNsLiteral plusSeconds(long seconds) { + return new TimeStampNsLiteral(toLocalDateTime().plusSeconds(seconds)); + } + + public void setMinValue() { + TimeStampNsLiteral minimum = createMinValue(); + year = minimum.year; + month = minimum.month; + day = minimum.day; + hour = minimum.hour; + minute = minimum.minute; + second = minimum.second; + nanosecond = minimum.nanosecond; + } + + public long getYear() { + return year; + } + + public long getMonth() { + return month; + } + + public long getDay() { + return day; + } + + public long getHour() { + return hour; + } + + public long getMinute() { + return minute; + } + + public long getSecond() { + return second; + } + + public long getMicrosecond() { + return nanosecond / 1000; + } + + public long getNanosecond() { + return nanosecond; + } + + @Override + public long getLongValue() { + return (year * 10000 + month * 100 + day) * 1000000L + hour * 10000 + minute * 100 + second; + } + + @Override + public double getDoubleValue() { + return getLongValue(); + } + + public double getDoubleValueAsDateTime() { + return getDoubleValue(); + } + + @Override + public int hashCode() { + int legacyHash = Long.hashCode(getLongValue()); + if (nanosecond % 1000 == 0) { + return legacyHash; + } + return 31 * legacyHash + Long.hashCode(nanosecond); + } + + @Override + public R accept(ExprVisitor visitor, C context) { + return visitor.visitTimeStampNsLiteral(this, context); + } +} diff --git a/fe/fe-catalog/src/main/java/org/apache/doris/catalog/AggregateType.java b/fe/fe-catalog/src/main/java/org/apache/doris/catalog/AggregateType.java index 2bcdc2165f68db..a49644ce505b89 100644 --- a/fe/fe-catalog/src/main/java/org/apache/doris/catalog/AggregateType.java +++ b/fe/fe-catalog/src/main/java/org/apache/doris/catalog/AggregateType.java @@ -86,6 +86,7 @@ public enum AggregateType { primitiveTypeList.add(PrimitiveType.DATETIME); primitiveTypeList.add(PrimitiveType.DATEV2); primitiveTypeList.add(PrimitiveType.DATETIMEV2); + primitiveTypeList.add(PrimitiveType.TIMESTAMP_NS); primitiveTypeList.add(PrimitiveType.TIMESTAMPTZ); primitiveTypeList.add(PrimitiveType.CHAR); primitiveTypeList.add(PrimitiveType.VARCHAR); @@ -108,6 +109,7 @@ public enum AggregateType { primitiveTypeList.add(PrimitiveType.DATETIME); primitiveTypeList.add(PrimitiveType.DATEV2); primitiveTypeList.add(PrimitiveType.DATETIMEV2); + primitiveTypeList.add(PrimitiveType.TIMESTAMP_NS); primitiveTypeList.add(PrimitiveType.TIMESTAMPTZ); primitiveTypeList.add(PrimitiveType.CHAR); primitiveTypeList.add(PrimitiveType.VARCHAR); diff --git a/fe/fe-catalog/src/main/java/org/apache/doris/catalog/ColumnType.java b/fe/fe-catalog/src/main/java/org/apache/doris/catalog/ColumnType.java index 483f22e2425f16..d3e6ef3fbbcf64 100644 --- a/fe/fe-catalog/src/main/java/org/apache/doris/catalog/ColumnType.java +++ b/fe/fe-catalog/src/main/java/org/apache/doris/catalog/ColumnType.java @@ -149,17 +149,26 @@ public abstract class ColumnType { schemaChangeMatrix[PrimitiveType.DATETIME.ordinal()][PrimitiveType.DATEV2.ordinal()] = true; schemaChangeMatrix[PrimitiveType.DATE.ordinal()][PrimitiveType.DATETIMEV2.ordinal()] = true; schemaChangeMatrix[PrimitiveType.DATETIME.ordinal()][PrimitiveType.DATETIMEV2.ordinal()] = true; + schemaChangeMatrix[PrimitiveType.DATE.ordinal()][PrimitiveType.TIMESTAMP_NS.ordinal()] = true; + schemaChangeMatrix[PrimitiveType.DATETIME.ordinal()][PrimitiveType.TIMESTAMP_NS.ordinal()] = true; schemaChangeMatrix[PrimitiveType.DATE.ordinal()][PrimitiveType.DATEV2.ordinal()] = true; schemaChangeMatrix[PrimitiveType.DATETIMEV2.ordinal()][PrimitiveType.DATE.ordinal()] = true; + schemaChangeMatrix[PrimitiveType.TIMESTAMP_NS.ordinal()][PrimitiveType.DATE.ordinal()] = true; schemaChangeMatrix[PrimitiveType.DATEV2.ordinal()][PrimitiveType.DATETIME.ordinal()] = true; schemaChangeMatrix[PrimitiveType.DATETIMEV2.ordinal()][PrimitiveType.DATEV2.ordinal()] = true; + schemaChangeMatrix[PrimitiveType.TIMESTAMP_NS.ordinal()][PrimitiveType.DATEV2.ordinal()] = true; schemaChangeMatrix[PrimitiveType.DATEV2.ordinal()][PrimitiveType.DATETIMEV2.ordinal()] = true; + schemaChangeMatrix[PrimitiveType.DATEV2.ordinal()][PrimitiveType.TIMESTAMP_NS.ordinal()] = true; schemaChangeMatrix[PrimitiveType.DATETIMEV2.ordinal()][PrimitiveType.DATETIME.ordinal()] = true; + schemaChangeMatrix[PrimitiveType.TIMESTAMP_NS.ordinal()][PrimitiveType.DATETIME.ordinal()] = true; schemaChangeMatrix[PrimitiveType.DATEV2.ordinal()][PrimitiveType.DATE.ordinal()] = true; // we should support schema change between different precision schemaChangeMatrix[PrimitiveType.DATETIMEV2.ordinal()][PrimitiveType.DATETIMEV2.ordinal()] = true; + schemaChangeMatrix[PrimitiveType.DATETIMEV2.ordinal()][PrimitiveType.TIMESTAMP_NS.ordinal()] = true; + schemaChangeMatrix[PrimitiveType.TIMESTAMP_NS.ordinal()][PrimitiveType.DATETIMEV2.ordinal()] = true; + schemaChangeMatrix[PrimitiveType.TIMESTAMP_NS.ordinal()][PrimitiveType.TIMESTAMP_NS.ordinal()] = true; // Currently, we do not support schema change between complex types with subtypes. schemaChangeMatrix[PrimitiveType.ARRAY.ordinal()][PrimitiveType.ARRAY.ordinal()] = true; diff --git a/fe/fe-catalog/src/main/java/org/apache/doris/persist/gson/GsonUtilsCatalog.java b/fe/fe-catalog/src/main/java/org/apache/doris/persist/gson/GsonUtilsCatalog.java index ec65e8db39df99..13bee42ee1e91d 100644 --- a/fe/fe-catalog/src/main/java/org/apache/doris/persist/gson/GsonUtilsCatalog.java +++ b/fe/fe-catalog/src/main/java/org/apache/doris/persist/gson/GsonUtilsCatalog.java @@ -54,6 +54,7 @@ import org.apache.doris.analysis.SlotRef; import org.apache.doris.analysis.StringLiteral; import org.apache.doris.analysis.StructLiteral; +import org.apache.doris.analysis.TimeStampNsLiteral; import org.apache.doris.analysis.TimeV2Literal; import org.apache.doris.analysis.TimestampArithmeticExpr; import org.apache.doris.analysis.TryCastExpr; @@ -131,6 +132,7 @@ public class GsonUtilsCatalog { .registerSubtype(ArrayLiteral.class, ArrayLiteral.class.getSimpleName()) .registerSubtype(BoolLiteral.class, BoolLiteral.class.getSimpleName()) .registerSubtype(DateLiteral.class, DateLiteral.class.getSimpleName()) + .registerSubtype(TimeStampNsLiteral.class, TimeStampNsLiteral.class.getSimpleName()) .registerSubtype(IPv4Literal.class, IPv4Literal.class.getSimpleName()) .registerSubtype(IPv6Literal.class, IPv6Literal.class.getSimpleName()) .registerSubtype(JsonLiteral.class, JsonLiteral.class.getSimpleName()) diff --git a/fe/fe-connector/fe-connector-adbc/src/main/java/org/apache/doris/connector/adbc/AdbcTypeMapper.java b/fe/fe-connector/fe-connector-adbc/src/main/java/org/apache/doris/connector/adbc/AdbcTypeMapper.java index c1b5b2d24cbaef..ca395afb26663b 100644 --- a/fe/fe-connector/fe-connector-adbc/src/main/java/org/apache/doris/connector/adbc/AdbcTypeMapper.java +++ b/fe/fe-connector/fe-connector-adbc/src/main/java/org/apache/doris/connector/adbc/AdbcTypeMapper.java @@ -50,7 +50,7 @@ */ public final class AdbcTypeMapper { - /** Doris DATETIMEV2/TIMESTAMPTZ scale is capped at 6 digits; Arrow nanosecond precision has 9. */ + /** Doris DATETIMEV2/TIMESTAMPTZ scale is capped at 6 digits. */ private static final int MAX_DATETIME_SCALE = 6; private static final int MAX_DECIMAL128_PRECISION = 38; private static final int MAX_DECIMAL256_PRECISION = 76; @@ -160,6 +160,10 @@ private static ConnectorType decimalType(String columnName, ArrowType.Decimal ty } private static ConnectorType timestampType(ArrowType.Timestamp type) { + boolean zoned = type.getTimezone() != null && !type.getTimezone().isEmpty(); + if (!zoned && type.getUnit() == org.apache.arrow.vector.types.TimeUnit.NANOSECOND) { + return ConnectorType.of("TIMESTAMP_NS"); + } int scale; switch (type.getUnit()) { case SECOND: @@ -169,8 +173,8 @@ private static ConnectorType timestampType(ArrowType.Timestamp type) { scale = 3; break; case NANOSECOND: - // Truncated rather than rejected: sub-microsecond precision is rare in stored data, and - // refusing the column would make whole tables unreadable over a fractional digit. + // Zoned nanosecond values cannot use the zone-free TIMESTAMP_NS type. TIMESTAMPTZ + // currently carries at most microseconds, so retain its existing scale here. scale = MAX_DATETIME_SCALE; break; default: @@ -187,7 +191,6 @@ private static ConnectorType timestampType(ArrowType.Timestamp type) { // who asked for wall clocks from one who said nothing at all, and honouring it would force // DATETIMEV2 on every adbc catalog. This connector's default is TIMESTAMPTZ. Making the // property settable here needs fe-core to let a connector supply its own default first. - boolean zoned = type.getTimezone() != null && !type.getTimezone().isEmpty(); return ConnectorType.of(zoned ? "TIMESTAMPTZ" : "DATETIMEV2", scale, 0); } diff --git a/fe/fe-connector/fe-connector-adbc/src/test/java/org/apache/doris/connector/adbc/AdbcTypeMapperTest.java b/fe/fe-connector/fe-connector-adbc/src/test/java/org/apache/doris/connector/adbc/AdbcTypeMapperTest.java index b49efdda68187e..f7281434b62e5f 100644 --- a/fe/fe-connector/fe-connector-adbc/src/test/java/org/apache/doris/connector/adbc/AdbcTypeMapperTest.java +++ b/fe/fe-connector/fe-connector-adbc/src/test/java/org/apache/doris/connector/adbc/AdbcTypeMapperTest.java @@ -125,10 +125,8 @@ void timestampScaleFollowsTheArrowUnit() { } @Test - void nanosecondTimestampsTruncateRatherThanFail() { - // Doris tops out at 6 fractional digits. Rejecting the column would make whole tables unreadable - // over a precision difference that stored data rarely uses. - Assertions.assertEquals(ConnectorType.of("DATETIMEV2", 6, 0), + void unzonedNanosecondTimestampsMapWithoutPrecisionLoss() { + Assertions.assertEquals(ConnectorType.of("TIMESTAMP_NS"), map(new ArrowType.Timestamp(TimeUnit.NANOSECOND, null))); } @@ -136,6 +134,8 @@ void nanosecondTimestampsTruncateRatherThanFail() { void zonedTimestampsMapToTimestamptz() { Assertions.assertEquals(ConnectorType.of("TIMESTAMPTZ", 6, 0), map(new ArrowType.Timestamp(TimeUnit.MICROSECOND, "UTC"))); + Assertions.assertEquals(ConnectorType.of("TIMESTAMPTZ", 6, 0), + map(new ArrowType.Timestamp(TimeUnit.NANOSECOND, "UTC"))); } @Test diff --git a/fe/fe-connector/fe-connector-iceberg/src/main/java/org/apache/doris/connector/iceberg/IcebergPredicateConverter.java b/fe/fe-connector/fe-connector-iceberg/src/main/java/org/apache/doris/connector/iceberg/IcebergPredicateConverter.java index 329023ead0bf07..564e476d3b886f 100644 --- a/fe/fe-connector/fe-connector-iceberg/src/main/java/org/apache/doris/connector/iceberg/IcebergPredicateConverter.java +++ b/fe/fe-connector/fe-connector-iceberg/src/main/java/org/apache/doris/connector/iceberg/IcebergPredicateConverter.java @@ -331,6 +331,8 @@ private Object extractIcebergLiteral(Type icebergType, ConnectorLiteral literal) return date.toString(); case TIMESTAMP: return toMicros(date.atStartOfDay(), icebergType); + case TIMESTAMP_NANO: + return toNanos(date.atStartOfDay(), icebergType); default: return null; } @@ -342,6 +344,8 @@ private Object extractIcebergLiteral(Type icebergType, ConnectorLiteral literal) return dorisDateTimeString(dateTime); case TIMESTAMP: return toMicros(dateTime, icebergType); + case TIMESTAMP_NANO: + return toNanos(dateTime, icebergType); default: return null; } @@ -413,6 +417,7 @@ private Object extractIcebergLiteral(Type icebergType, ConnectorLiteral literal) case DOUBLE: case TIME: case TIMESTAMP: + case TIMESTAMP_NANO: case DATE: case DECIMAL: return longValue; @@ -423,6 +428,7 @@ private Object extractIcebergLiteral(Type icebergType, ConnectorLiteral literal) String string = (String) value; switch (id) { case TIMESTAMP: + case TIMESTAMP_NANO: if (mode == Mode.SCAN) { // Legacy IcebergUtils.extractDorisLiteral returns the raw string for a TIMESTAMP column and // lets the iceberg bind-check accept only a well-formed ISO timestamp; a date-only or @@ -440,7 +446,11 @@ private Object extractIcebergLiteral(Type icebergType, ConnectorLiteral literal) // conflict-detection util (IcebergConflictDetectionFilterUtils) delegate to. Null (drop) when // not a parseable datetime. LocalDateTime parsedTs = parseDorisDateTime(string); - return parsedTs == null ? null : toMicros(parsedTs, icebergType); + if (parsedTs == null) { + return null; + } + return id == TypeID.TIMESTAMP + ? toMicros(parsedTs, icebergType) : toNanos(parsedTs, icebergType); case DATE: case TIME: case STRING: @@ -484,6 +494,17 @@ private long toMicros(LocalDateTime dateTime, Type icebergType) { return instant.getEpochSecond() * 1_000_000L + instant.getNano() / 1000L; } + private Long toNanos(LocalDateTime dateTime, Type icebergType) { + ZoneId zone = ((Types.TimestampNanoType) icebergType).shouldAdjustToUTC() + ? sessionZone : ZoneOffset.UTC; + Instant instant = dateTime.atZone(zone).toInstant(); + try { + return Math.addExact(Math.multiplyExact(instant.getEpochSecond(), 1_000_000_000L), instant.getNano()); + } catch (ArithmeticException e) { + return null; + } + } + // Parse a Doris-format datetime string ("yyyy-MM-dd HH:mm:ss[.fraction]") -- or a date-only string, taken // at start-of-day -- to a LocalDateTime, or null when unparseable. Normalizes the space separator to ISO // 'T' so java.time's ISO parsers accept the Doris rendering (mirrors legacy IcebergNereidsUtils' string -> diff --git a/fe/fe-connector/fe-connector-iceberg/src/main/java/org/apache/doris/connector/iceberg/IcebergTypeMapping.java b/fe/fe-connector/fe-connector-iceberg/src/main/java/org/apache/doris/connector/iceberg/IcebergTypeMapping.java index 9336efdcfdb60a..e6a3ab4dfeede1 100644 --- a/fe/fe-connector/fe-connector-iceberg/src/main/java/org/apache/doris/connector/iceberg/IcebergTypeMapping.java +++ b/fe/fe-connector/fe-connector-iceberg/src/main/java/org/apache/doris/connector/iceberg/IcebergTypeMapping.java @@ -149,6 +149,13 @@ private static ConnectorType fromPrimitive(Type.PrimitiveType primitive, return ConnectorType.of("TIMESTAMPTZ", ICEBERG_DATETIME_SCALE_MS, 0); } return ConnectorType.of("DATETIMEV2", ICEBERG_DATETIME_SCALE_MS, 0); + case TIMESTAMP_NANO: + if (!((Types.TimestampNanoType) primitive).shouldAdjustToUTC()) { + return ConnectorType.of("TIMESTAMP_NS"); + } + // TIMESTAMP_NS is zone-free. Mapping Iceberg's nanosecond zoned instant to it would + // silently change the value under non-UTC sessions. + return ConnectorType.of("UNSUPPORTED"); case TIME: // iceberg TIME has no Doris analogue -> UNSUPPORTED (explicit, byte-parity with legacy // IcebergUtils which also mapped TIME to Type.UNSUPPORTED). @@ -217,6 +224,8 @@ static Type toIcebergPrimitive(ConnectorType type) { return Types.TimestampType.withoutZone(); case "TIMESTAMPTZ": return Types.TimestampType.withZone(); + case "TIMESTAMP_NS": + return Types.TimestampNanoType.withoutZone(); default: throw new DorisConnectorException("Unsupported type for Iceberg: " + type.getTypeName()); } diff --git a/fe/fe-connector/fe-connector-iceberg/src/test/java/org/apache/doris/connector/iceberg/IcebergPredicateConverterTest.java b/fe/fe-connector/fe-connector-iceberg/src/test/java/org/apache/doris/connector/iceberg/IcebergPredicateConverterTest.java index 1f903ddbae526a..e2a9059e63941c 100644 --- a/fe/fe-connector/fe-connector-iceberg/src/test/java/org/apache/doris/connector/iceberg/IcebergPredicateConverterTest.java +++ b/fe/fe-connector/fe-connector-iceberg/src/test/java/org/apache/doris/connector/iceberg/IcebergPredicateConverterTest.java @@ -313,6 +313,18 @@ public void timestamptzLiteralUsesSessionZone() { Assertions.assertEquals(8L * 3600 * 1_000_000L, utcMicros - cstMicros); } + @Test + public void timestampNsLiteralPreservesAllNineDigits() { + Schema nano = new Schema( + Types.NestedField.required(1, "ts", Types.TimestampNanoType.withoutZone())); + LocalDateTime dt = LocalDateTime.of(1969, 12, 31, 23, 59, 59, 999999999); + ConnectorComparison cmp = new ConnectorComparison(ConnectorComparison.Operator.EQ, + new ConnectorColumnRef("ts", ConnectorType.of("TIMESTAMP_NS")), + new ConnectorLiteral(ConnectorType.of("TIMESTAMP_NS"), dt)); + Assertions.assertEquals(-1L, + singleMicros(new IcebergPredicateConverter(nano, ZoneOffset.UTC).convert(cmp))); + } + private static long singleMicros(List out) { Assertions.assertEquals(1, out.size()); Object value = ((org.apache.iceberg.expressions.UnboundPredicate) out.get(0)).literal().value(); diff --git a/fe/fe-connector/fe-connector-iceberg/src/test/java/org/apache/doris/connector/iceberg/IcebergSchemaBuilderTest.java b/fe/fe-connector/fe-connector-iceberg/src/test/java/org/apache/doris/connector/iceberg/IcebergSchemaBuilderTest.java index 4eac0ff0abe308..bbbd1b0b5f2645 100644 --- a/fe/fe-connector/fe-connector-iceberg/src/test/java/org/apache/doris/connector/iceberg/IcebergSchemaBuilderTest.java +++ b/fe/fe-connector/fe-connector-iceberg/src/test/java/org/apache/doris/connector/iceberg/IcebergSchemaBuilderTest.java @@ -99,6 +99,15 @@ public void testTimestampTzMapsToWithZone() { Assertions.assertTrue(((Types.TimestampType) type).shouldAdjustToUTC()); } + @Test + public void testTimestampNsMapsToNanosecondTimestampWithoutZone() { + Schema schema = IcebergSchemaBuilder.buildSchema(Collections.singletonList( + col("ts", ConnectorType.of("TIMESTAMP_NS"), true))); + Type type = schema.findField("ts").type(); + Assertions.assertEquals(Type.TypeID.TIMESTAMP_NANO, type.typeId()); + Assertions.assertFalse(((Types.TimestampNanoType) type).shouldAdjustToUTC()); + } + @Test public void testNullabilityAndFieldIdAndComment() { ConnectorColumn nullable = new ConnectorColumn("a", ConnectorType.of("INT"), "the a col", true, null, false); diff --git a/fe/fe-connector/fe-connector-iceberg/src/test/java/org/apache/doris/connector/iceberg/IcebergTypeMappingReadTest.java b/fe/fe-connector/fe-connector-iceberg/src/test/java/org/apache/doris/connector/iceberg/IcebergTypeMappingReadTest.java index 97f995ecf60eba..555cd7c748ed1e 100644 --- a/fe/fe-connector/fe-connector-iceberg/src/test/java/org/apache/doris/connector/iceberg/IcebergTypeMappingReadTest.java +++ b/fe/fe-connector/fe-connector-iceberg/src/test/java/org/apache/doris/connector/iceberg/IcebergTypeMappingReadTest.java @@ -95,7 +95,7 @@ public void unknownAndV3TypesDegradeToUnsupportedByDesign() { // This test PINS the graceful-degradation choice: MUTATION making either default arm throw -> red, // surfacing that the accepted deviation was reverted. (The write direction toIcebergPrimitive still // throws — see toIcebergPrimitiveRejectsUnrepresentableTypes if present / the connector's CREATE path.) - Assertions.assertEquals("UNSUPPORTED", mapOff(Types.TimestampNanoType.withoutZone()).getTypeName()); + Assertions.assertEquals("TIMESTAMP_NS", mapOff(Types.TimestampNanoType.withoutZone()).getTypeName()); Assertions.assertEquals("UNSUPPORTED", mapOff(Types.TimestampNanoType.withZone()).getTypeName()); Assertions.assertEquals("UNSUPPORTED", mapOff(Types.GeometryType.crs84()).getTypeName()); Assertions.assertEquals("UNSUPPORTED", mapOff(Types.GeographyType.crs84()).getTypeName()); diff --git a/fe/fe-connector/fe-connector-paimon/src/main/java/org/apache/doris/connector/paimon/PaimonPredicateConverter.java b/fe/fe-connector/fe-connector-paimon/src/main/java/org/apache/doris/connector/paimon/PaimonPredicateConverter.java index 5fb90b3beb9732..9aea0a97469d95 100644 --- a/fe/fe-connector/fe-connector-paimon/src/main/java/org/apache/doris/connector/paimon/PaimonPredicateConverter.java +++ b/fe/fe-connector/fe-connector-paimon/src/main/java/org/apache/doris/connector/paimon/PaimonPredicateConverter.java @@ -336,6 +336,9 @@ private Object convertLiteralValue(ConnectorLiteral literal, DataType paimonType // stored stats and risk false file/partition pruning = silent data loss. if (value instanceof LocalDateTime) { LocalDateTime dt = (LocalDateTime) value; + if (literal.getType().getTypeName().equalsIgnoreCase("TIMESTAMP_NS")) { + return Timestamp.fromLocalDateTime(dt); + } long millis = dt.toInstant(ZoneOffset.UTC).toEpochMilli(); return Timestamp.fromEpochMillis(millis); } diff --git a/fe/fe-connector/fe-connector-paimon/src/main/java/org/apache/doris/connector/paimon/PaimonScanPlanProvider.java b/fe/fe-connector/fe-connector-paimon/src/main/java/org/apache/doris/connector/paimon/PaimonScanPlanProvider.java index 2b801ebbb7a4e2..0a1e5b712e006f 100644 --- a/fe/fe-connector/fe-connector-paimon/src/main/java/org/apache/doris/connector/paimon/PaimonScanPlanProvider.java +++ b/fe/fe-connector/fe-connector-paimon/src/main/java/org/apache/doris/connector/paimon/PaimonScanPlanProvider.java @@ -84,6 +84,7 @@ import org.apache.paimon.types.DataType; import org.apache.paimon.types.MapType; import org.apache.paimon.types.RowType; +import org.apache.paimon.types.TimestampType; import org.apache.paimon.utils.InstantiationUtil; import org.apache.paimon.utils.RowDataToObjectArrayConverter; import org.apache.thrift.TDeserializer; @@ -2174,6 +2175,12 @@ private static TField buildField(DataType dataType) { TColumnType columnType = new TColumnType(); TNestedField nestedField = new TNestedField(); switch (dataType.getTypeRoot()) { + case TIMESTAMP_WITHOUT_TIME_ZONE: { + TimestampType timestampType = (TimestampType) dataType; + columnType.setType(timestampType.getPrecision() > 6 + ? TPrimitiveType.TIMESTAMP_NS : TPrimitiveType.DATETIMEV2); + break; + } case ARRAY: { columnType.setType(TPrimitiveType.ARRAY); TArrayField arrayField = new TArrayField(); diff --git a/fe/fe-connector/fe-connector-paimon/src/main/java/org/apache/doris/connector/paimon/PaimonTypeMapping.java b/fe/fe-connector/fe-connector-paimon/src/main/java/org/apache/doris/connector/paimon/PaimonTypeMapping.java index 1f29ccd1194df7..db42cfbf8df7bd 100644 --- a/fe/fe-connector/fe-connector-paimon/src/main/java/org/apache/doris/connector/paimon/PaimonTypeMapping.java +++ b/fe/fe-connector/fe-connector-paimon/src/main/java/org/apache/doris/connector/paimon/PaimonTypeMapping.java @@ -149,13 +149,14 @@ private static ConnectorType toDecimalType(DecimalType type) { } private static ConnectorType toTimestampType(DataType dataType) { - int scale = DEFAULT_TIMESTAMP_SCALE; if (dataType instanceof TimestampType) { - scale = Math.min(((TimestampType) dataType).getPrecision(), MAX_TIMESTAMP_SCALE); - } else if (dataType instanceof LocalZonedTimestampType) { - scale = Math.min(((LocalZonedTimestampType) dataType).getPrecision(), MAX_TIMESTAMP_SCALE); + int precision = ((TimestampType) dataType).getPrecision(); + if (precision > MAX_TIMESTAMP_SCALE) { + return ConnectorType.of("TIMESTAMP_NS"); + } + return ConnectorType.of("DATETIMEV2", precision, 0); } - return ConnectorType.of("DATETIMEV2", scale, 0); + return ConnectorType.of("DATETIMEV2", DEFAULT_TIMESTAMP_SCALE, 0); } private static ConnectorType toTimestampTzType(DataType dataType, Options options) { @@ -255,6 +256,8 @@ public static DataType toPaimonType(ConnectorType type) { // scale is intentionally dropped to match DorisToPaimonTypeVisitor.atomic, and it // is a plain timestamp (NOT LocalZonedTimestampType). return new TimestampType(); + case "TIMESTAMP_NS": + return new TimestampType(9); case "VARBINARY": return new VarBinaryType(VarBinaryType.MAX_LENGTH); case "VARIANT": diff --git a/fe/fe-connector/fe-connector-paimon/src/test/java/org/apache/doris/connector/paimon/PaimonPredicateConverterTest.java b/fe/fe-connector/fe-connector-paimon/src/test/java/org/apache/doris/connector/paimon/PaimonPredicateConverterTest.java index 6fcf5564d590c5..9f3733bd174a31 100644 --- a/fe/fe-connector/fe-connector-paimon/src/test/java/org/apache/doris/connector/paimon/PaimonPredicateConverterTest.java +++ b/fe/fe-connector/fe-connector-paimon/src/test/java/org/apache/doris/connector/paimon/PaimonPredicateConverterTest.java @@ -56,11 +56,16 @@ public class PaimonPredicateConverterTest { /** Builds `col = literal` over a single-column RowType of the given paimon type. */ private static List convertEq( RowType rowType, String colName, Object literalValue) { + return convertEq(rowType, colName, literalValue, ANY); + } + + private static List convertEq( + RowType rowType, String colName, Object literalValue, ConnectorType literalType) { PaimonPredicateConverter converter = new PaimonPredicateConverter(rowType); ConnectorComparison cmp = new ConnectorComparison( ConnectorComparison.Operator.EQ, new ConnectorColumnRef(colName, ANY), - new ConnectorLiteral(ANY, literalValue)); + new ConnectorLiteral(literalType, literalValue)); return converter.convert(cmp); } @@ -88,6 +93,21 @@ public void ntzPushedWithUtcSemantics() { "NTZ literal must be the wall clock converted via fixed UTC (legacy GMT parity)"); } + @Test + public void timestampNsPredicatePreservesAllNineDigits() { + RowType rowType = RowType.builder().field("ts", DataTypes.TIMESTAMP(9)).build(); + LocalDateTime literal = LocalDateTime.of(1969, 12, 31, 23, 59, 59, 999999999); + List predicates = convertEq( + rowType, "ts", literal, ConnectorType.of("TIMESTAMP_NS")); + + Assertions.assertEquals(1, predicates.size()); + LeafPredicate leaf = (LeafPredicate) predicates.get(0); + Assertions.assertEquals(Timestamp.fromLocalDateTime(literal), leaf.literals().get(0)); + Timestamp pushed = (Timestamp) leaf.literals().get(0); + Assertions.assertEquals(-1L, pushed.getMillisecond()); + Assertions.assertEquals(999999, pushed.getNanoOfMillisecond()); + } + @Test public void ltzNotPushed() { RowType rowType = RowType.builder() diff --git a/fe/fe-connector/fe-connector-paimon/src/test/java/org/apache/doris/connector/paimon/PaimonScanPlanProviderTest.java b/fe/fe-connector/fe-connector-paimon/src/test/java/org/apache/doris/connector/paimon/PaimonScanPlanProviderTest.java index ce8c337a65de43..1022e35c4ea94c 100644 --- a/fe/fe-connector/fe-connector-paimon/src/test/java/org/apache/doris/connector/paimon/PaimonScanPlanProviderTest.java +++ b/fe/fe-connector/fe-connector-paimon/src/test/java/org/apache/doris/connector/paimon/PaimonScanPlanProviderTest.java @@ -2332,9 +2332,9 @@ public void backendOptionsDropRetiredFileReaderAsyncOptOut() { @Test public void buildSchemaInfoCarriesFieldIdsNamesAndScalarTag() { // WHY (B-1a): BE matches file<->table columns BY paimon field id; the id+name on each top-level - // field are the join keys. Scalars carry a single placeholder tag because BE reads type.type only - // as a nested-vs-scalar discriminator. MUTATION: dropping setId/setName -> ids/names absent -> BE - // can't field-id-match -> falls back to by-name (the silent wrong-rows bug). + // field are the join keys. Ordinary scalars carry a single placeholder tag because BE reads + // type.type only as a nested-vs-scalar discriminator. MUTATION: dropping setId/setName -> + // ids/names absent -> BE can't field-id-match -> falls back to by-name (the silent wrong-rows bug). List fields = Arrays.asList( new DataField(7, "id", DataTypes.INT()), new DataField(9, "name", DataTypes.STRING())); @@ -2355,13 +2355,18 @@ public void buildSchemaInfoCarriesFieldIdsNamesAndScalarTag() { public void buildSchemaInfoCarriesTimestampSemantics() { List fields = Arrays.asList( new DataField(7, "ts", DataTypes.TIMESTAMP(9)), - new DataField(8, "ts_ltz", DataTypes.TIMESTAMP_WITH_LOCAL_TIME_ZONE(9))); + new DataField(8, "ts_us", DataTypes.TIMESTAMP(6)), + new DataField(9, "ts_ltz", DataTypes.TIMESTAMP_WITH_LOCAL_TIME_ZONE(9))); List top = PaimonScanPlanProvider.buildSchemaInfo(3L, fields, false) .getRootField().getFields(); Assertions.assertFalse(top.get(0).getFieldPtr().isTimestampIsAdjustedToUtc()); - Assertions.assertTrue(top.get(1).getFieldPtr().isTimestampIsAdjustedToUtc()); + Assertions.assertEquals(TPrimitiveType.TIMESTAMP_NS, + top.get(0).getFieldPtr().getType().getType()); + Assertions.assertEquals(TPrimitiveType.DATETIMEV2, + top.get(1).getFieldPtr().getType().getType()); + Assertions.assertTrue(top.get(2).getFieldPtr().isTimestampIsAdjustedToUtc()); } @Test diff --git a/fe/fe-connector/fe-connector-paimon/src/test/java/org/apache/doris/connector/paimon/PaimonTypeMappingReadTest.java b/fe/fe-connector/fe-connector-paimon/src/test/java/org/apache/doris/connector/paimon/PaimonTypeMappingReadTest.java index 81d5e305f841e1..96c5be9ba442c2 100644 --- a/fe/fe-connector/fe-connector-paimon/src/test/java/org/apache/doris/connector/paimon/PaimonTypeMappingReadTest.java +++ b/fe/fe-connector/fe-connector-paimon/src/test/java/org/apache/doris/connector/paimon/PaimonTypeMappingReadTest.java @@ -22,6 +22,7 @@ import org.apache.paimon.types.DataField; import org.apache.paimon.types.IntType; import org.apache.paimon.types.RowType; +import org.apache.paimon.types.TimestampType; import org.apache.paimon.types.VarCharType; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -81,4 +82,16 @@ public void nestedStructFieldCommentAndNullabilityCarried() { Assertions.assertTrue(struct.isChildNullable(1), "a nullable nested struct field stays nullable"); } + + @Test + public void nanosecondTimestampMapsToTimestampNs() { + ConnectorType timestampNs = PaimonTypeMapping.toConnectorType( + new TimestampType(9), PaimonTypeMapping.Options.DEFAULT); + Assertions.assertEquals("TIMESTAMP_NS", timestampNs.getTypeName()); + + ConnectorType microsecond = PaimonTypeMapping.toConnectorType( + new TimestampType(6), PaimonTypeMapping.Options.DEFAULT); + Assertions.assertEquals("DATETIMEV2", microsecond.getTypeName()); + Assertions.assertEquals(6, microsecond.getPrecision()); + } } diff --git a/fe/fe-connector/fe-connector-paimon/src/test/java/org/apache/doris/connector/paimon/PaimonTypeMappingToPaimonTest.java b/fe/fe-connector/fe-connector-paimon/src/test/java/org/apache/doris/connector/paimon/PaimonTypeMappingToPaimonTest.java index ba32a64d385990..784c2dbdd89d9d 100644 --- a/fe/fe-connector/fe-connector-paimon/src/test/java/org/apache/doris/connector/paimon/PaimonTypeMappingToPaimonTest.java +++ b/fe/fe-connector/fe-connector-paimon/src/test/java/org/apache/doris/connector/paimon/PaimonTypeMappingToPaimonTest.java @@ -94,6 +94,12 @@ public void datetimeDropsScaleToNoArgTimestamp() { Assertions.assertEquals(expected, PaimonTypeMapping.toPaimonType(ConnectorType.of("DATETIME"))); } + @Test + public void timestampNsMapsToPrecisionNineTimestamp() { + Assertions.assertEquals(new TimestampType(9), + PaimonTypeMapping.toPaimonType(ConnectorType.of("TIMESTAMP_NS"))); + } + @Test public void decimalCarriesPrecisionAndScale() { // WHY: every decimal family member carries precision/scale through verbatim. MUTATION: diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java index 597a006707ed2c..533536f022ac00 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java @@ -149,6 +149,8 @@ public String getValue() { format = "yyyy-MM-dd HH:mm:ss.SSSSS"; } else if (precision == 6) { format = "yyyy-MM-dd HH:mm:ss.SSSSSS"; + } else { + format = "yyyy-MM-dd HH:mm:ss." + "S".repeat((int) precision); } return LocalDateTime.now(TimeUtils.getTimeZone().toZoneId()) .format(DateTimeFormatter.ofPattern(format)); @@ -323,10 +325,11 @@ public static void validateDefaultValue(Type type, String defaultValue, DefaultV switch (primitiveType) { case DATETIME: case DATETIMEV2: + case TIMESTAMP_NS: case TIMESTAMPTZ: break; default: - throw new AnalysisException("Types other than DATETIME and DATETIMEV2 " + throw new AnalysisException("Types other than DATETIME, DATETIMEV2, TIMESTAMP_NS and TIMESTAMPTZ " + "cannot use current_timestamp as the default value"); } } else if (null != defaultValueExprDef @@ -400,16 +403,19 @@ public static void validateDefaultValue(Type type, String defaultValue, DefaultV break; case DATETIME: case DATETIMEV2: + case TIMESTAMP_NS: case TIMESTAMPTZ: if (defaultValueExprDef == null) { - DateLiteralUtils.createDateLiteral(defaultValue, scalarType); + DateLiteralUtils.createLiteral(defaultValue, scalarType); } else { if (defaultValueExprDef.getExprName().equals(DefaultValue.NOW)) { if (defaultValueExprDef.getPrecision() != null) { Long defaultValuePrecision = defaultValueExprDef.getPrecision(); String typeStr = scalarType.toString(); - int typePrecision = - Integer.parseInt(typeStr.substring(typeStr.indexOf("(") + 1, typeStr.indexOf(")"))); + int typePrecision = scalarType.isTimeStampNs() + ? ScalarType.TIMESTAMP_NS_SCALE + : Integer.parseInt(typeStr.substring( + typeStr.indexOf("(") + 1, typeStr.indexOf(")"))); if (defaultValuePrecision > typePrecision) { typeStr = typeStr.replace("V2", ""); throw new AnalysisException("default value precision: " + defaultValue diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteralUtils.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteralUtils.java index 84d8f2bb0ea22b..3ba1c4fe7c3e0f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteralUtils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteralUtils.java @@ -21,6 +21,7 @@ import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.util.TimeUtils; +import org.apache.doris.nereids.util.DateUtils; import com.google.common.base.Preconditions; @@ -37,28 +38,46 @@ import java.util.regex.Pattern; import javax.annotation.Nullable; -/** - * Utility class providing a static factory method for creating {@link DateLiteral} instances - * from string representations. This replicates the parsing logic of the - * {@code DateLiteral(String, Type)} constructor and its {@code init()} method. - */ +/** Utility methods for parsing legacy date-like literals from strings. */ public class DateLiteralUtils { private static final Pattern HAS_OFFSET_PART = Pattern.compile("[\\+\\-]\\d{2}:\\d{2}"); + private static final long NANOSECONDS_PER_SECOND = 1_000_000_000L; + private static final long[] NANOSECOND_SCALE_FACTORS = { + 1_000_000_000L, 100_000_000L, 10_000_000L, 1_000_000L, 100_000L, + 10_000L, 1_000L, 100L, 10L, 1L + }; private DateLiteralUtils() { } /** - * Creates a {@link DateLiteral} by parsing the given string, replicating the exact behavior - * of the {@code DateLiteral(String, Type)} constructor and its internal {@code init()} method. + * Parse a legacy date-like literal. * - * @param s the date/datetime string to parse - * @param type the target date type, or {@code null} for auto-detection - * @return a new {@link DateLiteral} instance - * @throws AnalysisException if the string cannot be parsed or the resulting value is out of range + *

TIMESTAMP_NS has a dedicated {@link TimeStampNsLiteral} because its signed epoch-nanosecond + * representation and range differ from {@link DateLiteral}. Callers that can receive any + * date-like type must therefore use this method and retain the {@link LiteralExpr} result.

+ */ + public static LiteralExpr createLiteral(String s, @Nullable Type type) throws AnalysisException { + return createDateTimeLiteral(s, type); + } + + /** + * Parse a literal backed by {@link DateLiteral}. + * + *

This compatibility entry point deliberately rejects TIMESTAMP_NS instead of hiding it in + * DateLiteral's microsecond fields. New date-generic callers should use {@link #createLiteral}.

*/ public static DateLiteral createDateLiteral(String s, @Nullable Type type) throws AnalysisException { + LiteralExpr literal = createDateTimeLiteral(s, type); + if (!(literal instanceof DateLiteral)) { + throw new AnalysisException("date literal [" + s + + "] resolves to TIMESTAMP_NS; use DateLiteralUtils.createLiteral instead"); + } + return (DateLiteral) literal; + } + + private static LiteralExpr createDateTimeLiteral(String s, @Nullable Type type) throws AnalysisException { try { if (type != null) { Preconditions.checkArgument(type.isDateType()); @@ -66,10 +85,14 @@ public static DateLiteral createDateLiteral(String s, @Nullable Type type) throw TemporalAccessor dateTime = null; boolean parsed = false; ZoneId sourceZone = null; + // Every pre-existing date type retains its six-digit parsing contract. A null type is + // used when decoding an untyped DATE_LITERAL thrift node, where 7-9 digits are the only + // information available to infer TIMESTAMP_NS. + boolean parseNanoseconds = type == null || type.isTimeStampNs(); // parse timezone if (haveTimeZoneOffset(s) || haveTimeZoneName(s)) { - String tzString = new String(); + String tzString; if (haveTimeZoneName(s)) { // GMT, UTC+8, Z[, CN, Asia/Shanghai] int split = getTimeZoneSplitPos(s); Preconditions.checkArgument(split > 0); @@ -84,6 +107,14 @@ public static DateLiteral createDateLiteral(String s, @Nullable Type type) throw sourceZone = ZoneId.of(tzString); } + int nanosecondGuardDigit = -1; + if (parseNanoseconds) { + // java.time parses at most nine fractional digits. Keep the tenth digit separately + // so fixed-scale TIMESTAMP_NS can still implement the same half-up rounding as BE. + nanosecondGuardDigit = DateUtils.getNanosecondGuardDigit(s); + s = DateUtils.truncateFractionalSecondForJavaParser(s); + } + if (!s.contains("-")) { // handle format like 20210106, but should not handle 2021-1-6 for (DateTimeFormatter formatter : DateLiteral.formatterList) { @@ -140,7 +171,8 @@ public static DateLiteral createDateLiteral(String s, @Nullable Type type) throw throw new AnalysisException("Invalid date value: " + s); } if (timePart.length == 0 && type != null - && (type.equals(Type.DATETIME) || type.equals(Type.DATETIMEV2))) { + && (type.equals(Type.DATETIME) || type.equals(Type.DATETIMEV2) + || type.equals(Type.TIMESTAMP_NS))) { throw new AnalysisException("Invalid datetime value: " + s); } for (int i = 0; i < timePart.length; i++) { @@ -159,7 +191,10 @@ public static DateLiteral createDateLiteral(String s, @Nullable Type type) throw ? timePart[i].split("\\.")[0].length() : timePart[i].length(), "s"))); if (timePart[i].contains(".")) { - builder.appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true); + builder.appendFraction(parseNanoseconds + ? ChronoField.NANO_OF_SECOND : ChronoField.MICRO_OF_SECOND, + 0, parseNanoseconds ? ScalarType.TIMESTAMP_NS_SCALE + : ScalarType.MAX_DATETIMEV2_SCALE, true); } break; default: @@ -183,33 +218,49 @@ public static DateLiteral createDateLiteral(String s, @Nullable Type type) throw long hour = getOrDefault(dateTime, ChronoField.HOUR_OF_DAY, 0); long minute = getOrDefault(dateTime, ChronoField.MINUTE_OF_HOUR, 0); long second = getOrDefault(dateTime, ChronoField.SECOND_OF_MINUTE, 0); - long microsecond = getOrDefault(dateTime, ChronoField.MICRO_OF_SECOND, 0); + long nanosecond = parseNanoseconds + ? getOrDefault(dateTime, ChronoField.NANO_OF_SECOND, 0) + : getOrDefault(dateTime, ChronoField.MICRO_OF_SECOND, 0) * 1000L; if (type != null) { - if (microsecond != 0 && type.isDatetime()) { + if (nanosecond != 0 && type.isDatetime()) { int dotIndex = s.lastIndexOf("."); int scale = s.length() - dotIndex - 1; type = ScalarType.createDatetimeV2Type(scale); } } else { - if (hour == 0 && minute == 0 && second == 0 && microsecond == 0) { + // Type inference must observe the scale-9 rounded fraction. For example, + // .1234560005 rounds to .123456001 and therefore requires TIMESTAMP_NS rather + // than DATETIMEV2(6). A carry is also time-bearing even when its rounded fraction + // becomes zero, as in 00:00:00.9999999995 -> 00:00:01.000000000. + long inferredNanosecond = nanosecond + (nanosecondGuardDigit >= 5 ? 1 : 0); + boolean fractionalCarry = inferredNanosecond == NANOSECONDS_PER_SECOND; + if (fractionalCarry) { + inferredNanosecond = 0; + } + if (hour == 0 && minute == 0 && second == 0 + && inferredNanosecond == 0 && !fractionalCarry) { type = ScalarType.getDefaultDateType(Type.DATE); } else { type = ScalarType.getDefaultDateType(Type.DATETIME); - if (type.isDatetimeV2() && microsecond != 0) { - int scale = 6; - for (int i = 0; i < 6; i++) { - if (microsecond % Math.pow(10.0, i + 1) > 0) { - break; - } else { - scale -= 1; - } + if (type.isDatetimeV2() && inferredNanosecond != 0) { + int scale = ScalarType.TIMESTAMP_NS_SCALE; + long fractionalSecond = inferredNanosecond; + while (fractionalSecond % 10 == 0) { + fractionalSecond /= 10; + scale--; } - type = ScalarType.createDatetimeV2Type(scale); + type = scale > ScalarType.MAX_DATETIMEV2_SCALE + ? ScalarType.createTimeStampNsType() + : ScalarType.createDatetimeV2Type(scale); } } } + LocalDateTime literalDateTime = LocalDateTime.of( + (int) year, (int) month, (int) day, + (int) hour, (int) minute, (int) second, (int) nanosecond); + // Recompute the timezone offset using the target date rather than // Instant.now(), so DST-sensitive zones (e.g. America/Chicago) // produce the correct shift regardless of when the code runs. @@ -228,29 +279,36 @@ public static DateLiteral createDateLiteral(String s, @Nullable Type type) throw if (type != null && type.isTimeStampTz()) { dorisZone = ZoneId.of("UTC"); } - LocalDateTime parsedLdt = LocalDateTime.of( - (int) year, (int) month, (int) day, - (int) hour, (int) minute, (int) second); - Instant targetInstant = parsedLdt.atZone(sourceZone).toInstant(); - LocalDateTime destLdt = LocalDateTime.ofInstant(targetInstant, dorisZone); - year = destLdt.getYear(); - month = destLdt.getMonthValue(); - day = destLdt.getDayOfMonth(); - hour = destLdt.getHour(); - minute = destLdt.getMinute(); - second = destLdt.getSecond(); - // microsecond is preserved from the original parse, matching - // the original init() behavior (not affected by zone conversion) + Instant targetInstant = literalDateTime.atZone(sourceZone).toInstant(); + literalDateTime = LocalDateTime.ofInstant(targetInstant, dorisZone); + } + + if (type.isTimeStampNs()) { + literalDateTime = roundFractionalSecond( + literalDateTime, ScalarType.TIMESTAMP_NS_SCALE, nanosecondGuardDigit); + TimeStampNsLiteral result = new TimeStampNsLiteral( + literalDateTime.getYear(), literalDateTime.getMonthValue(), + literalDateTime.getDayOfMonth(), literalDateTime.getHour(), + literalDateTime.getMinute(), literalDateTime.getSecond(), + literalDateTime.getNano()); + result.checkValueValid(); + return result; } - // Construct DateLiteral using the appropriate constructor based on the determined type DateLiteral result; if (type.isDate() || type.isDateV2()) { - result = new DateLiteral(year, month, day, type); - } else if (microsecond != 0 && (type.isDatetimeV2() || type.isTimeStampTz())) { - result = new DateLiteral(year, month, day, hour, minute, second, microsecond, type); + result = new DateLiteral(literalDateTime.getYear(), literalDateTime.getMonthValue(), + literalDateTime.getDayOfMonth(), type); + } else if (literalDateTime.getNano() != 0 + && (type.isDatetimeV2() || type.isTimeStampTz())) { + result = new DateLiteral(literalDateTime.getYear(), literalDateTime.getMonthValue(), + literalDateTime.getDayOfMonth(), literalDateTime.getHour(), + literalDateTime.getMinute(), literalDateTime.getSecond(), + literalDateTime.getNano() / 1000L, type); } else { - result = new DateLiteral(year, month, day, hour, minute, second, type); + result = new DateLiteral(literalDateTime.getYear(), literalDateTime.getMonthValue(), + literalDateTime.getDayOfMonth(), literalDateTime.getHour(), + literalDateTime.getMinute(), literalDateTime.getSecond(), type); } if (result.checkRange() || result.checkDate()) { @@ -266,6 +324,25 @@ private static int getOrDefault(TemporalAccessor accessor, ChronoField field, in return accessor.isSupported(field) ? accessor.get(field) : defaultValue; } + /** + * Round a fractional second half-up to the target scale. + * + *

At TIMESTAMP_NS scale 9 there is no discarded digit inside the parsed value, so the + * separately retained tenth digit decides whether to add one nanosecond. A rounded value of one + * billion nanoseconds is carried into the next civil second, including date rollover.

+ */ + private static LocalDateTime roundFractionalSecond( + LocalDateTime value, int scale, int nanosecondGuardDigit) { + long factor = NANOSECOND_SCALE_FACTORS[scale]; + long roundingOffset = factor == 1 + ? (nanosecondGuardDigit >= 5 ? 1 : 0) : factor / 2; + long roundedNanosecond = (value.getNano() + roundingOffset) / factor * factor; + if (roundedNanosecond == NANOSECONDS_PER_SECOND) { + return value.withNano(0).plusSeconds(1); + } + return value.withNano((int) roundedNanosecond); + } + private static boolean haveTimeZoneOffset(String arg) { Preconditions.checkArgument(arg.length() > 6); return HAS_OFFSET_PART.matcher(arg.substring(arg.length() - 6)).matches(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToSqlVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToSqlVisitor.java index 3bbbbc902cc9c0..003fca86bfd959 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToSqlVisitor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToSqlVisitor.java @@ -86,6 +86,11 @@ public String visitDateLiteral(DateLiteral expr, ToSqlParams context) { return "'" + expr.getStringValue() + "'"; } + @Override + public String visitTimeStampNsLiteral(TimeStampNsLiteral expr, ToSqlParams context) { + return "'" + expr.getStringValue() + "'"; + } + @Override public String visitTimeV2Literal(TimeV2Literal expr, ToSqlParams context) { return "\"" + expr.getStringValue() + "\""; diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToStringValueVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToStringValueVisitor.java index 0c59cf99f5b068..46fe332ccbcff9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToStringValueVisitor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToStringValueVisitor.java @@ -105,6 +105,14 @@ public String visitDateLiteral(DateLiteral expr, StringValueContext ctx) { return value; } + @Override + public String visitTimeStampNsLiteral(TimeStampNsLiteral expr, StringValueContext ctx) { + if (ctx.isInComplexType()) { + return wrapWithQuotes(expr.getStringValue(), ctx); + } + return expr.getStringValue(); + } + @Override public String visitFloatLiteral(FloatLiteral expr, StringValueContext ctx) { String value; diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToThriftVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToThriftVisitor.java index 3df252e8fed56b..3f1521ff376459 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToThriftVisitor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToThriftVisitor.java @@ -202,6 +202,18 @@ public Void visitDateLiteral(DateLiteral expr, TExprNode msg) { return null; } + @Override + public Void visitTimeStampNsLiteral(TimeStampNsLiteral expr, TExprNode msg) { + msg.node_type = TExprNodeType.DATE_LITERAL; + msg.date_literal = new TDateLiteral(expr.getStringValue()); + try { + expr.checkValueValid(); + } catch (AnalysisException e) { + LOG.warn("meet invalid value when plan to translate " + expr + " to thrift node"); + } + return null; + } + @Override public Void visitTimeV2Literal(TimeV2Literal expr, TExprNode msg) { msg.node_type = TExprNodeType.TIMEV2_LITERAL; diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExprUtils.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExprUtils.java index b9a5d392a349ac..2e0d833f652179 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExprUtils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExprUtils.java @@ -68,8 +68,9 @@ public static LiteralExpr createLiteral(String value, Type type) throws Analysis case DATETIME: case DATEV2: case DATETIMEV2: + case TIMESTAMP_NS: case TIMESTAMPTZ: - literalExpr = DateLiteralUtils.createDateLiteral(value, type); + literalExpr = DateLiteralUtils.createLiteral(value, type); break; case IPV4: literalExpr = new IPv4Literal(value); @@ -104,6 +105,8 @@ public static LiteralExpr createInfinity(Type type, boolean isMax) throws Analys case DATETIMEV2: case TIMESTAMPTZ: return DateLiteral.createMinValue(type); + case TIMESTAMP_NS: + return TimeStampNsLiteral.createMinValue(); default: throw new AnalysisException("Invalid data type for creating infinity: " + type); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/OutFileClause.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/OutFileClause.java index dce783c0fc9e01..f5cd445225d026 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/OutFileClause.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/OutFileClause.java @@ -258,6 +258,7 @@ private String dorisTypeToOrcTypeMap(Type dorisType) throws AnalysisException { orcType = "date"; break; case DATETIMEV2: + case TIMESTAMP_NS: orcType = "timestamp"; break; case TIMESTAMPTZ: @@ -384,6 +385,7 @@ private void analyzeForOrcFormat(List resultExprs, List colLabels) checkOrcType(schema.second, "date", true, resultType.getPrimitiveType().toString()); break; case DATETIMEV2: + case TIMESTAMP_NS: checkOrcType(schema.second, "timestamp", true, resultType.getPrimitiveType().toString()); break; case TIMESTAMPTZ: diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/PartitionExprUtil.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/PartitionExprUtil.java index 43e1b53badc91c..96421206125a1a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/PartitionExprUtil.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/PartitionExprUtil.java @@ -36,6 +36,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -100,6 +101,11 @@ public static FunctionIntervalInfo getFunctionIntervalInfo(ArrayList parti public static DateLiteral getRangeEnd(DateLiteral beginTime, FunctionIntervalInfo intervalInfo) throws AnalysisException { + LocalDateTime endTime = getRangeEnd(beginTime.getTimeFormatter(), intervalInfo); + return endTime == null ? null : new DateLiteral(endTime, beginTime.getType()); + } + + private static LocalDateTime getRangeEnd(LocalDateTime beginTime, FunctionIntervalInfo intervalInfo) { String timeUnit = intervalInfo.timeUnit; long interval = intervalInfo.interval; switch (timeUnit) { @@ -161,11 +167,18 @@ public static Map getAddPartitionClauseFromPartitionValu if (partitionType == PartitionType.RANGE) { String beginTime = curPartitionValues.get(0); // have check range type size must be 1 Type partitionColumnType = partitionColumn.get(0).getType(); - DateLiteral beginDateTime = DateLiteralUtils.createDateLiteral(beginTime, partitionColumnType); + LiteralExpr beginDateTime = DateLiteralUtils.createLiteral(beginTime, partitionColumnType); + LocalDateTime beginLocalDateTime = beginDateTime instanceof DateLiteral + ? ((DateLiteral) beginDateTime).getTimeFormatter() + : ((TimeStampNsLiteral) beginDateTime).toLocalDateTime(); partitionName += String.format(DATETIME_NAME_FORMATTER, - beginDateTime.getYear(), beginDateTime.getMonth(), beginDateTime.getDay(), - beginDateTime.getHour(), beginDateTime.getMinute(), beginDateTime.getSecond()); - DateLiteral endDateTime = getRangeEnd(beginDateTime, intervalInfo); + beginLocalDateTime.getYear(), beginLocalDateTime.getMonthValue(), + beginLocalDateTime.getDayOfMonth(), beginLocalDateTime.getHour(), + beginLocalDateTime.getMinute(), beginLocalDateTime.getSecond()); + LocalDateTime endLocalDateTime = getRangeEnd(beginLocalDateTime, intervalInfo); + LiteralExpr endDateTime = beginDateTime instanceof DateLiteral + ? new DateLiteral(endLocalDateTime, beginDateTime.getType()) + : new TimeStampNsLiteral(endLocalDateTime); partitionKeyDesc = createPartitionKeyDescWithRange(beginDateTime, endDateTime, partitionColumnType); } else if (partitionType == PartitionType.LIST) { List> listValues = new ArrayList<>(); @@ -232,8 +245,8 @@ public static Map getAddPartitionClauseFromPartitionValu return result; } - private static PartitionKeyDesc createPartitionKeyDescWithRange(DateLiteral beginDateTime, - DateLiteral endDateTime, Type partitionColumnType) throws AnalysisException { + private static PartitionKeyDesc createPartitionKeyDescWithRange(LiteralExpr beginDateTime, + LiteralExpr endDateTime, Type partitionColumnType) throws AnalysisException { PartitionValue lowerValue = getPartitionFromDate(partitionColumnType, beginDateTime); PartitionValue upperValue = getPartitionFromDate(partitionColumnType, endDateTime); return PartitionKeyDesc.createFixed( @@ -241,7 +254,7 @@ private static PartitionKeyDesc createPartitionKeyDescWithRange(DateLiteral begi Collections.singletonList(upperValue)); } - private static PartitionValue getPartitionFromDate(Type partitionColumnType, DateLiteral dateLiteral) + private static PartitionValue getPartitionFromDate(Type partitionColumnType, LiteralExpr dateLiteral) throws AnalysisException { // check out of range. try { @@ -252,15 +265,19 @@ private static PartitionValue getPartitionFromDate(Type partitionColumnType, Dat return PartitionValue.MAX_VALUE; } + LocalDateTime dateTime = dateLiteral instanceof DateLiteral + ? ((DateLiteral) dateLiteral).getTimeFormatter() + : ((TimeStampNsLiteral) dateLiteral).toLocalDateTime(); String timeString; if (partitionColumnType.isDate() || partitionColumnType.isDateV2()) { - timeString = String.format(DATE_FORMATTER, dateLiteral.getYear(), dateLiteral.getMonth(), - dateLiteral.getDay()); + timeString = String.format(DATE_FORMATTER, dateTime.getYear(), dateTime.getMonthValue(), + dateTime.getDayOfMonth()); } else if (partitionColumnType.isDatetime() || partitionColumnType.isDatetimeV2() + || partitionColumnType.isTimeStampNs() || partitionColumnType.isTimeStampTz()) { timeString = String.format(DATETIME_FORMATTER, - dateLiteral.getYear(), dateLiteral.getMonth(), dateLiteral.getDay(), - dateLiteral.getHour(), dateLiteral.getMinute(), dateLiteral.getSecond()); + dateTime.getYear(), dateTime.getMonthValue(), dateTime.getDayOfMonth(), + dateTime.getHour(), dateTime.getMinute(), dateTime.getSecond()); } else { throw new AnalysisException( "not support range partition with column type : " + partitionColumnType.toString()); diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/ColumnToProtobuf.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/ColumnToProtobuf.java index d9c17012a64d28..aa0c89a85bd25c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/ColumnToProtobuf.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/ColumnToProtobuf.java @@ -153,6 +153,7 @@ static int getFieldLengthByType(PrimitiveType type, int stringLength) throws Ddl case DATETIME: return 8; case DATETIMEV2: + case TIMESTAMP_NS: case TIMESTAMPTZ: return 8; case FLOAT: diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/PartitionInfo.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/PartitionInfo.java index f23954280f3a65..ab6f610003a74f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/PartitionInfo.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/PartitionInfo.java @@ -24,6 +24,7 @@ import org.apache.doris.analysis.PartitionDesc; import org.apache.doris.analysis.PartitionValue; import org.apache.doris.analysis.SinglePartitionDesc; +import org.apache.doris.analysis.TimeStampNsLiteral; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.Config; import org.apache.doris.common.DdlException; @@ -398,7 +399,7 @@ public static List toPartitionValue(PartitionKey partitionKey) { return partitionKey.getKeys().stream().map(expr -> { if (expr == MaxLiteral.MAX_VALUE) { return PartitionValue.MAX_VALUE; - } else if (expr instanceof DateLiteral) { + } else if (expr instanceof DateLiteral || expr instanceof TimeStampNsLiteral) { return new PartitionValue(expr.getStringValue()); } else if (expr instanceof NullLiteral) { return new PartitionValue("NULL", true); diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/PartitionKey.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/PartitionKey.java index 3832876cd84401..e6d9daaf4bd43b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/PartitionKey.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/PartitionKey.java @@ -34,6 +34,7 @@ import org.apache.doris.nereids.trees.expressions.literal.DateTimeLiteral; import org.apache.doris.nereids.trees.expressions.literal.DateTimeV2Literal; import org.apache.doris.nereids.trees.expressions.literal.Literal; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.trees.expressions.literal.TimestampTzLiteral; import org.apache.doris.nereids.types.DataType; import org.apache.doris.nereids.types.TimeStampTzType; @@ -118,7 +119,8 @@ public static PartitionKey createPartitionKey(List keys, List keys) { value = expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE); } else { value = expr.getRealValue(); - if (expr instanceof DateLiteral) { - DateLiteral dateLiteral = (DateLiteral) expr; - value = dateLiteral.getStringValue(); + if (expr instanceof DateLiteral || expr instanceof org.apache.doris.analysis.TimeStampNsLiteral) { + value = expr.getStringValue(); } } if (keys.size() - 1 == i) { @@ -571,7 +580,11 @@ public PartitionKey deserialize(JsonElement json, java.lang.reflect.Type typeOfT LOG.warn("Value {} for partition key [type = {}] is invalid! This is a bug exists " + "in Doris 1.2.0 and fixed since Doris 1.2.1. You should create this table " + "again using Doris 1.2.1+ .", key.getStringValue(), type); - ((DateLiteral) key).setMinValue(); + if (key instanceof org.apache.doris.analysis.TimeStampNsLiteral) { + ((org.apache.doris.analysis.TimeStampNsLiteral) key).setMinValue(); + } else { + ((DateLiteral) key).setMinValue(); + } } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/util/DynamicPartitionUtil.java b/fe/fe-core/src/main/java/org/apache/doris/common/util/DynamicPartitionUtil.java index 729b87008c183a..b762345f1f8695 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/util/DynamicPartitionUtil.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/DynamicPartitionUtil.java @@ -799,6 +799,7 @@ public static String getPartitionFormat(Column column) throws DdlException { return DATE_FORMAT; } else if (column.getDataType().equals(PrimitiveType.DATETIME) || column.getDataType().equals(PrimitiveType.DATETIMEV2) + || column.getDataType().equals(PrimitiveType.TIMESTAMP_NS) || column.getDataType().equals(PrimitiveType.TIMESTAMPTZ)) { return DATETIME_FORMAT; } else if (PrimitiveType.getIntegerTypes().contains(column.getDataType())) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/util/FetchRemoteTabletSchemaUtil.java b/fe/fe-core/src/main/java/org/apache/doris/common/util/FetchRemoteTabletSchemaUtil.java index ac0541b3f143f1..9d475b1500106d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/util/FetchRemoteTabletSchemaUtil.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/FetchRemoteTabletSchemaUtil.java @@ -89,6 +89,7 @@ public FetchRemoteTabletSchemaUtil(List tablets) { typeMap.put("DATE", Type.DATE); typeMap.put("DATEV2", Type.DATEV2); typeMap.put("DATETIMEV2", Type.DATETIMEV2); + typeMap.put("TIMESTAMP_NS", Type.TIMESTAMP_NS); typeMap.put("DATETIME", Type.DATETIME); typeMap.put("DECIMAL32", Type.DECIMAL32); typeMap.put("DECIMAL64", Type.DECIMAL64); diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/util/PropertyAnalyzer.java b/fe/fe-core/src/main/java/org/apache/doris/common/util/PropertyAnalyzer.java index 0b56c1a244dda5..308c0b0bb9fdbb 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/util/PropertyAnalyzer.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/PropertyAnalyzer.java @@ -410,8 +410,10 @@ public static DataProperty analyzeDataProperty(Map properties, f } } else if (key.equalsIgnoreCase(PROPERTIES_STORAGE_COOLDOWN_TIME)) { try { + // Cooldown timestamps are stored in milliseconds, so DATETIMEV2(6) preserves their + // fractional part without imposing the narrower TIMESTAMP_NS epoch range. DateLiteral dateLiteral = DateLiteralUtils.createDateLiteral(value, - ScalarType.getDefaultDateType(Type.DATETIME)); + ScalarType.createDatetimeV2Type(6)); cooldownTimestamp = dateLiteral.unixTimestamp(TimeUtils.getTimeZone()); } catch (AnalysisException e) { LOG.warn("dateLiteral failed, use max cool down time", e); diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java b/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java index 0a4e8f967e310e..2f706a4c660492 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java @@ -78,6 +78,7 @@ public class Util { TYPE_STRING_MAP.put(PrimitiveType.DATETIME, "datetime"); TYPE_STRING_MAP.put(PrimitiveType.DATEV2, "datev2"); TYPE_STRING_MAP.put(PrimitiveType.DATETIMEV2, "datetimev2"); + TYPE_STRING_MAP.put(PrimitiveType.TIMESTAMP_NS, "timestamp_ns"); TYPE_STRING_MAP.put(PrimitiveType.TIMESTAMPTZ, "timestamptz"); TYPE_STRING_MAP.put(PrimitiveType.CHAR, "char(%d)"); TYPE_STRING_MAP.put(PrimitiveType.VARCHAR, "varchar(%d)"); diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/connector/converter/ExprToConnectorExpressionConverter.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/connector/converter/ExprToConnectorExpressionConverter.java index 36cd21e3194084..b79b6f72c1b8eb 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/connector/converter/ExprToConnectorExpressionConverter.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/connector/converter/ExprToConnectorExpressionConverter.java @@ -37,6 +37,7 @@ import org.apache.doris.analysis.NullLiteral; import org.apache.doris.analysis.SlotRef; import org.apache.doris.analysis.StringLiteral; +import org.apache.doris.analysis.TimeStampNsLiteral; import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.catalog.ArrayType; import org.apache.doris.catalog.MapType; @@ -299,6 +300,8 @@ private static ConnectorExpression convertLiteral(LiteralExpr literal) { return new ConnectorLiteral(ct, ((DecimalLiteral) literal).getValue()); } else if (literal instanceof StringLiteral) { return new ConnectorLiteral(ct, ((StringLiteral) literal).getValue()); + } else if (literal instanceof TimeStampNsLiteral) { + return new ConnectorLiteral(ct, ((TimeStampNsLiteral) literal).toLocalDateTime()); } else if (literal instanceof DateLiteral) { return convertDateLiteral((DateLiteral) literal, ct); } else { diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcMySQLClient.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcMySQLClient.java index bcdc9ccc03bd69..e6b8b56f91bf9d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcMySQLClient.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcMySQLClient.java @@ -450,11 +450,13 @@ private Type dorisTypeToDoris(JdbcFieldSchema fieldSchema) { case "DATETIMEV2": { int scale = (openParen == -1) ? 0 : Integer.parseInt(upperType.substring(openParen + 1, upperType.length() - 1)); - if (scale > 6) { - scale = 6; + if (scale > ScalarType.MAX_DATETIMEV2_SCALE) { + scale = ScalarType.MAX_DATETIMEV2_SCALE; } return ScalarType.createDatetimeV2Type(scale); } + case "TIMESTAMP_NS": + return ScalarType.createTimeStampNsType(); case "CHAR": case "CHARACTER": return ScalarType.createCharType(fieldSchema.requiredColumnSize()); diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/util/StatementSubmitter.java b/fe/fe-core/src/main/java/org/apache/doris/httpv2/util/StatementSubmitter.java index 60b44ec9384bfb..03c85ba771e2fd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/util/StatementSubmitter.java +++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/util/StatementSubmitter.java @@ -225,7 +225,8 @@ private ExecutionResultSet generateResultSet(ResultSet rs, long startTime, boole for (int i = 1; i <= colNum && (!isCopyStmt || i <= copyResult.length); ++i) { String type = rs.getMetaData().getColumnTypeName(i); if ("DATE".equalsIgnoreCase(type) || "DATETIME".equalsIgnoreCase(type) - || "DATEV2".equalsIgnoreCase(type) || "DATETIMEV2".equalsIgnoreCase(type)) { + || "DATEV2".equalsIgnoreCase(type) || "DATETIMEV2".equalsIgnoreCase(type) + || "TIMESTAMP_NS".equalsIgnoreCase(type)) { row.add(rs.getString(i)); } else { row.add(rs.getObject(i)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/util/streamresponse/JsonStreamResponse.java b/fe/fe-core/src/main/java/org/apache/doris/httpv2/util/streamresponse/JsonStreamResponse.java index ba77589b710d27..61afcffdcffde6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/util/streamresponse/JsonStreamResponse.java +++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/util/streamresponse/JsonStreamResponse.java @@ -154,7 +154,8 @@ private void writeResultSetData(ResultSet rs, JsonWriter jsonWriter, long startT for (int i = 1; i <= colNum; ++i) { String type = rs.getMetaData().getColumnTypeName(i); if ("DATE".equalsIgnoreCase(type) || "DATETIME".equalsIgnoreCase(type) - || "DATEV2".equalsIgnoreCase(type) || "DATETIMEV2".equalsIgnoreCase(type)) { + || "DATEV2".equalsIgnoreCase(type) || "DATETIMEV2".equalsIgnoreCase(type) + || "TIMESTAMP_NS".equalsIgnoreCase(type)) { row.add(rs.getString(i)); } else { row.add(rs.getObject(i)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionExprDateTrunc.java b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionExprDateTrunc.java index 6a23cabdb93e0a..f563c34f25659b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionExprDateTrunc.java +++ b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionExprDateTrunc.java @@ -247,7 +247,8 @@ private String dateTimeToStr(DateTimeV2Literal literal, if (partitionColumnType.isDate() || partitionColumnType.isDateV2()) { return String.format(PartitionExprUtil.DATE_FORMATTER, literal.getYear(), literal.getMonth(), literal.getDay()); - } else if (partitionColumnType.isDatetime() || partitionColumnType.isDatetimeV2()) { + } else if (partitionColumnType.isDatetime() || partitionColumnType.isDatetimeV2() + || partitionColumnType.isTimeStampNs()) { return String.format(PartitionExprUtil.DATETIME_FORMATTER, literal.getYear(), literal.getMonth(), literal.getDay(), literal.getHour(), literal.getMinute(), literal.getSecond()); diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlSerializer.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlSerializer.java index 4469830f320eb3..e67f843acefcdc 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlSerializer.java +++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlSerializer.java @@ -18,6 +18,7 @@ package org.apache.doris.mysql; import org.apache.doris.catalog.Column; +import org.apache.doris.catalog.MysqlColType; import org.apache.doris.catalog.ScalarType; import org.apache.doris.catalog.Type; @@ -187,7 +188,7 @@ public void writeField(FieldInfo fieldInfo, Type type) { // Column length: four byte integer writeInt4(getMysqlTypeLength(type)); // Column type: one byte integer - writeInt1(type.getPrimitiveType().toMysqlType().getCode()); + writeInt1(getMysqlResultType(type).getCode()); // Flags: two byte integer writeInt2(getMysqlFlags(type)); // Decimals: one byte integer @@ -216,7 +217,7 @@ public void writeField(String db, String table, Column column, boolean sendDefau // TODO(zhaochun): fix Column length: four byte integer writeInt4(getMysqlTypeLength(column.getType())); // Column type: one byte integer - writeInt1(column.getDataType().toMysqlType().getCode()); + writeInt1(getMysqlResultType(column.getType()).getCode()); // Flags: two byte integer writeInt2(getMysqlFlags(column.getType())); // Decimals: one byte integer @@ -251,7 +252,7 @@ public void writeField(String colName, Type type) { // Column length: four byte integer writeInt4(getMysqlTypeLength(type)); // Column type: one byte integer - writeInt1(type.getPrimitiveType().toMysqlType().getCode()); + writeInt1(getMysqlResultType(type).getCode()); // Flags: two byte integer writeInt2(getMysqlFlags(type)); // Decimals: one byte integer @@ -268,7 +269,7 @@ public void writeField(String colName, Type type) { * @param type * @return */ - private int getMysqlTypeLength(Type type) { + int getMysqlTypeLength(Type type) { switch (type.getPrimitiveType()) { // MySQL use Tinyint(1) to represent boolean case BOOLEAN: @@ -291,6 +292,9 @@ private int getMysqlTypeLength(Type type) { case TIMESTAMPTZ: // yyyy-MM-dd HH:mm:ss[.ffffff]+HH:mm return 32; + case TIMESTAMP_NS: + // yyyy-MM-dd HH:mm:ss.nnnnnnnnn + return 29; case DATETIME: case DATETIMEV2: { if (type.getPrimitiveType().isTimeType()) { @@ -332,6 +336,9 @@ private int getMysqlTypeLength(Type type) { // this is used for decimal scale public int getMysqlDecimals(Type type) { + if (isTimestampNs(type)) { + return 0; + } switch (type.getPrimitiveType()) { case DECIMALV2: case DECIMAL32: @@ -349,6 +356,17 @@ public int getMysqlDecimals(Type type) { } } + private MysqlColType getMysqlResultType(Type type) { + // MySQL's binary temporal value contains at most microseconds. TIMESTAMP_NS is + // serialized by BE as a length-encoded string so the metadata must advertise a string too. + return isTimestampNs(type) ? MysqlColType.MYSQL_TYPE_STRING + : type.getPrimitiveType().toMysqlType(); + } + + private boolean isTimestampNs(Type type) { + return type.isTimeStampNs(); + } + // see https://github.com/mysql/mysql-server/blob/trunk/include/mysql_com.h#L161 private int getMysqlFlags(Type type) { int flags = 0; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java index 05336a7771e784..669a51d860365b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java @@ -4201,7 +4201,7 @@ public ColumnDefinition visitColumnDef(ColumnDefContext ctx) { } else { defaultValue = Optional.of(DefaultValue .currentTimeStampDefaultValueWithPrecision( - Long.valueOf(ctx.defaultValuePrecision.getText()))); + Long.valueOf(ctx.defaultValuePrecision.getText()), colType)); } } else if (ctx.CURRENT_DATE() != null) { defaultValue = Optional.of(DefaultValue.CURRENT_DATE_DEFAULT_VALUE); @@ -4219,7 +4219,7 @@ public ColumnDefinition visitColumnDef(ColumnDefContext ctx) { } else { onUpdateDefaultValue = Optional.of(DefaultValue .currentTimeStampDefaultValueWithPrecision( - Long.valueOf(ctx.onUpdateValuePrecision.getText()))); + Long.valueOf(ctx.onUpdateValuePrecision.getText()), colType)); } } AggregateType aggType = null; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindSink.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindSink.java index 06fe765f004a50..be93c614ae0845 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindSink.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindSink.java @@ -72,6 +72,7 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.Substring; import org.apache.doris.nereids.trees.expressions.literal.Literal; import org.apache.doris.nereids.trees.expressions.literal.NullLiteral; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionRewriter; import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.commands.info.DMLCommandType; @@ -93,6 +94,7 @@ import org.apache.doris.nereids.types.coercion.CharacterType; import org.apache.doris.nereids.util.ExpressionUtils; import org.apache.doris.nereids.util.RelationUtil; +import org.apache.doris.nereids.util.TimestampNsDefaultValueUtils; import org.apache.doris.nereids.util.TypeCoercionUtils; import org.apache.doris.nereids.util.Utils; import org.apache.doris.qe.AutoCloseSessionVariable; @@ -466,15 +468,22 @@ private static Map getColumnToOutput( replaceMap.put(output.toSlot(), output.child()); } else { try { - Expression unboundDefaultValue = new NereidsParser().parseExpression( - column.getDefaultValueSql()); - Expression defualtValueExpression = ExpressionAnalyzer.analyzeFunction( - boundSink, ctx.cascadesContext, unboundDefaultValue); - if (defualtValueExpression instanceof Alias) { - defualtValueExpression = ((Alias) defualtValueExpression).child(); + Optional timestampNsDefault + = TimestampNsDefaultValueUtils.currentTimestampLiteral(column); + Expression defaultValueExpression; + if (timestampNsDefault.isPresent()) { + defaultValueExpression = timestampNsDefault.get(); + } else { + Expression unboundDefaultValue = new NereidsParser().parseExpression( + column.getDefaultValueSql()); + defaultValueExpression = ExpressionAnalyzer.analyzeFunction( + boundSink, ctx.cascadesContext, unboundDefaultValue); + if (defaultValueExpression instanceof Alias) { + defaultValueExpression = ((Alias) defaultValueExpression).child(); + } } Alias output = new Alias((TypeCoercionUtils.castIfNotSameType( - defualtValueExpression, DataType.fromCatalogType(column.getType()))), + defaultValueExpression, DataType.fromCatalogType(column.getType()))), column.getName()); columnToOutput.put(column.getName(), output); columnToReplaced.put(column.getName(), output.toSlot()); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinder.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinder.java index 4e1a768bd97fe9..48a46b894d3ae7 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinder.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinder.java @@ -100,6 +100,7 @@ import org.apache.doris.nereids.trees.expressions.literal.StringLikeLiteral; import org.apache.doris.nereids.trees.expressions.literal.TimestampTzLiteral; import org.apache.doris.nereids.trees.expressions.literal.format.DateTimeChecker; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.annotations.VisibleForTesting; @@ -403,6 +404,7 @@ private Expression processDateSub(TimeUnit unit, Expression timeStamp, Expressio } private Expression processDateFloor(TimeUnit unit, Expression timeStamp, Expression amount) { + boolean isTimeStampNs = timeStamp.getDataType() instanceof TimeStampNsType; boolean hasTimezone = false; if (timeStamp.getDataType() instanceof TimeStampTzType) { hasTimezone = true; @@ -413,21 +415,21 @@ private Expression processDateFloor(TimeUnit unit, Expression timeStamp, Express Expression e = hasTimezone ? TimestampTzLiteral.USE_IN_FLOOR_CEIL : DateTimeV2Literal.USE_IN_FLOOR_CEIL; switch (unit) { case YEAR: - return new YearFloor(timeStamp, amount, e); + return isTimeStampNs ? new YearFloor(timeStamp, amount) : new YearFloor(timeStamp, amount, e); case QUARTER: - return new QuarterFloor(timeStamp, amount, e); + return isTimeStampNs ? new QuarterFloor(timeStamp, amount) : new QuarterFloor(timeStamp, amount, e); case MONTH: - return new MonthFloor(timeStamp, amount, e); + return isTimeStampNs ? new MonthFloor(timeStamp, amount) : new MonthFloor(timeStamp, amount, e); case WEEK: - return new WeekFloor(timeStamp, amount, e); + return isTimeStampNs ? new WeekFloor(timeStamp, amount) : new WeekFloor(timeStamp, amount, e); case DAY: - return new DayFloor(timeStamp, amount, e); + return isTimeStampNs ? new DayFloor(timeStamp, amount) : new DayFloor(timeStamp, amount, e); case HOUR: - return new HourFloor(timeStamp, amount, e); + return isTimeStampNs ? new HourFloor(timeStamp, amount) : new HourFloor(timeStamp, amount, e); case MINUTE: - return new MinuteFloor(timeStamp, amount, e); + return isTimeStampNs ? new MinuteFloor(timeStamp, amount) : new MinuteFloor(timeStamp, amount, e); case SECOND: - return new SecondFloor(timeStamp, amount, e); + return isTimeStampNs ? new SecondFloor(timeStamp, amount) : new SecondFloor(timeStamp, amount, e); default: throw new AnalysisException("Unsupported time stamp floor time unit: " + unit + ", supported time unit: YEAR/QUARTER/MONTH/WEEK/DAY/HOUR/MINUTE/SECOND"); @@ -435,6 +437,7 @@ private Expression processDateFloor(TimeUnit unit, Expression timeStamp, Express } private Expression processDateCeil(TimeUnit unit, Expression timeStamp, Expression amount) { + boolean isTimeStampNs = timeStamp.getDataType() instanceof TimeStampNsType; boolean hasTimezone = false; if (timeStamp.getDataType() instanceof TimeStampTzType) { hasTimezone = true; @@ -445,21 +448,21 @@ private Expression processDateCeil(TimeUnit unit, Expression timeStamp, Expressi Expression e = hasTimezone ? TimestampTzLiteral.USE_IN_FLOOR_CEIL : DateTimeV2Literal.USE_IN_FLOOR_CEIL; switch (unit) { case YEAR: - return new YearCeil(timeStamp, amount, e); + return isTimeStampNs ? new YearCeil(timeStamp, amount) : new YearCeil(timeStamp, amount, e); case QUARTER: - return new QuarterCeil(timeStamp, amount, e); + return isTimeStampNs ? new QuarterCeil(timeStamp, amount) : new QuarterCeil(timeStamp, amount, e); case MONTH: - return new MonthCeil(timeStamp, amount, e); + return isTimeStampNs ? new MonthCeil(timeStamp, amount) : new MonthCeil(timeStamp, amount, e); case WEEK: - return new WeekCeil(timeStamp, amount, e); + return isTimeStampNs ? new WeekCeil(timeStamp, amount) : new WeekCeil(timeStamp, amount, e); case DAY: - return new DayCeil(timeStamp, amount, e); + return isTimeStampNs ? new DayCeil(timeStamp, amount) : new DayCeil(timeStamp, amount, e); case HOUR: - return new HourCeil(timeStamp, amount, e); + return isTimeStampNs ? new HourCeil(timeStamp, amount) : new HourCeil(timeStamp, amount, e); case MINUTE: - return new MinuteCeil(timeStamp, amount, e); + return isTimeStampNs ? new MinuteCeil(timeStamp, amount) : new MinuteCeil(timeStamp, amount, e); case SECOND: - return new SecondCeil(timeStamp, amount, e); + return isTimeStampNs ? new SecondCeil(timeStamp, amount) : new SecondCeil(timeStamp, amount, e); default: throw new AnalysisException("Unsupported time stamp ceil time unit: " + unit + ", supported time unit: YEAR/QUARTER/MONTH/WEEK/DAY/HOUR/MINUTE/SECOND"); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/check/CheckCast.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/check/CheckCast.java index 4328360f821249..8a917e77b713f0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/check/CheckCast.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/check/CheckCast.java @@ -50,6 +50,7 @@ import org.apache.doris.nereids.types.StringType; import org.apache.doris.nereids.types.StructField; import org.apache.doris.nereids.types.StructType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.TimeV2Type; import org.apache.doris.nereids.types.TinyIntType; @@ -88,6 +89,7 @@ public class CheckCast implements ExpressionPatternRuleFactory { allowedTypes.remove(DateV2Type.class); allowedTypes.remove(DateTimeType.class); allowedTypes.remove(DateTimeV2Type.class); + allowedTypes.remove(TimeStampNsType.class); allowedTypes.remove(TimeV2Type.class); allowedTypes.add(JsonType.class); allowedTypes.add(VariantType.class); @@ -117,6 +119,7 @@ public class CheckCast implements ExpressionPatternRuleFactory { allowedTypes.add(DateV2Type.class); allowedTypes.add(DateTimeType.class); allowedTypes.add(DateTimeV2Type.class); + allowedTypes.add(TimeStampNsType.class); allowToStringLikeType(allowedTypes); allowedTypes.add(VariantType.class); strictCastWhiteList.put(DateType.class, allowedTypes); @@ -130,6 +133,7 @@ public class CheckCast implements ExpressionPatternRuleFactory { allowedTypes.add(DateV2Type.class); allowedTypes.add(DateTimeType.class); allowedTypes.add(DateTimeV2Type.class); + allowedTypes.add(TimeStampNsType.class); allowedTypes.add(TimeV2Type.class); allowToStringLikeType(allowedTypes); allowedTypes.add(VariantType.class); @@ -143,15 +147,32 @@ public class CheckCast implements ExpressionPatternRuleFactory { allowedTypes.add(DateV2Type.class); allowedTypes.add(DateTimeType.class); allowedTypes.add(DateTimeV2Type.class); + allowedTypes.add(TimeStampNsType.class); allowedTypes.add(TimeV2Type.class); allowToStringLikeType(allowedTypes); allowedTypes.add(VariantType.class); allowedTypes.add(TimeStampTzType.class); strictCastWhiteList.put(DateTimeV2Type.class, allowedTypes); + // TimestampNs + allowedTypes = Sets.newHashSet(); + allowedTypes.add(BigIntType.class); + allowedTypes.add(LargeIntType.class); + allowedTypes.add(DateType.class); + allowedTypes.add(DateV2Type.class); + allowedTypes.add(DateTimeType.class); + allowedTypes.add(DateTimeV2Type.class); + allowedTypes.add(TimeStampNsType.class); + allowedTypes.add(TimeV2Type.class); + allowToStringLikeType(allowedTypes); + allowedTypes.add(VariantType.class); + allowedTypes.add(TimeStampTzType.class); + strictCastWhiteList.put(TimeStampNsType.class, allowedTypes); + // timestamp tz allowedTypes = Sets.newHashSet(); allowedTypes.add(DateTimeV2Type.class); + allowedTypes.add(TimeStampNsType.class); allowedTypes.add(TimeStampTzType.class); allowToStringLikeType(allowedTypes); strictCastWhiteList.put(TimeStampTzType.class, allowedTypes); @@ -167,6 +188,7 @@ public class CheckCast implements ExpressionPatternRuleFactory { allowedTypes.add(DateV2Type.class); allowedTypes.add(DateTimeType.class); allowedTypes.add(DateTimeV2Type.class); + allowedTypes.add(TimeStampNsType.class); allowedTypes.add(TimeV2Type.class); allowToStringLikeType(allowedTypes); allowedTypes.add(VariantType.class); @@ -179,6 +201,7 @@ public class CheckCast implements ExpressionPatternRuleFactory { allowedTypes.add(IPv6Type.class); allowedTypes.add(VarBinaryType.class); allowedTypes.add(TimeStampTzType.class); + allowedTypes.add(TimeStampNsType.class); allowToComplexType(allowedTypes); allowedTypes.remove(HllType.class); allowedTypes.remove(BitmapType.class); @@ -253,6 +276,7 @@ public class CheckCast implements ExpressionPatternRuleFactory { allowedTypes.remove(DateV2Type.class); allowedTypes.remove(DateTimeType.class); allowedTypes.remove(DateTimeV2Type.class); + allowedTypes.remove(TimeStampNsType.class); allowedTypes.remove(TimeV2Type.class); allowedTypes.add(ArrayType.class); allowedTypes.add(StructType.class); @@ -281,6 +305,7 @@ public class CheckCast implements ExpressionPatternRuleFactory { allowedTypes.add(DoubleType.class); unStrictCastWhiteList.put(DateTimeType.class, allowedTypes); unStrictCastWhiteList.put(DateTimeV2Type.class, allowedTypes); + unStrictCastWhiteList.put(TimeStampNsType.class, allowedTypes); // Time allowedTypes = Sets.newHashSet(); @@ -304,6 +329,7 @@ private static void allowToBasicType(Set> allowedTypes allowedTypes.add(DateV2Type.class); allowedTypes.add(DateTimeType.class); allowedTypes.add(DateTimeV2Type.class); + allowedTypes.add(TimeStampNsType.class); allowedTypes.add(TimeV2Type.class); allowToStringLikeType(allowedTypes); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/DateFunctionRewrite.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/DateFunctionRewrite.java index deba786d44cee6..92b89221b4364b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/DateFunctionRewrite.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/DateFunctionRewrite.java @@ -21,6 +21,7 @@ import org.apache.doris.nereids.rules.expression.ExpressionPatternRuleFactory; import org.apache.doris.nereids.rules.expression.ExpressionRuleType; import org.apache.doris.nereids.trees.expressions.And; +import org.apache.doris.nereids.trees.expressions.ComparisonPredicate; import org.apache.doris.nereids.trees.expressions.EqualTo; import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.expressions.GreaterThan; @@ -34,6 +35,7 @@ import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal; import org.apache.doris.nereids.types.DateTimeType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.collect.ImmutableList; @@ -65,6 +67,9 @@ public List> buildRules() { } private static Expression rewriteEqualTo(EqualTo equalTo) { + if (isTimeStampNsDateComparison(equalTo)) { + return rewriteTimeStampNsDateComparison(equalTo); + } if (equalTo.left() instanceof Date) { // V1 if (equalTo.left().child(0).getDataType() instanceof DateTimeType @@ -91,6 +96,9 @@ private static Expression rewriteEqualTo(EqualTo equalTo) { } private static Expression rewriteGreaterThan(GreaterThan greaterThan) { + if (isTimeStampNsDateComparison(greaterThan)) { + return rewriteTimeStampNsDateComparison(greaterThan); + } if (greaterThan.left() instanceof Date) { // V1 if (greaterThan.left().child(0).getDataType() instanceof DateTimeType @@ -111,6 +119,9 @@ private static Expression rewriteGreaterThan(GreaterThan greaterThan) { } private static Expression rewriteGreaterThanEqual(GreaterThanEqual greaterThanEqual) { + if (isTimeStampNsDateComparison(greaterThanEqual)) { + return rewriteTimeStampNsDateComparison(greaterThanEqual); + } if (greaterThanEqual.left() instanceof Date) { // V1 if (greaterThanEqual.left().child(0).getDataType() instanceof DateTimeType @@ -130,6 +141,9 @@ private static Expression rewriteGreaterThanEqual(GreaterThanEqual greaterThanEq } private static Expression rewriteLessThan(LessThan lessThan) { + if (isTimeStampNsDateComparison(lessThan)) { + return rewriteTimeStampNsDateComparison(lessThan); + } if (lessThan.left() instanceof Date) { // V1 if (lessThan.left().child(0).getDataType() instanceof DateTimeType @@ -149,6 +163,9 @@ private static Expression rewriteLessThan(LessThan lessThan) { } private static Expression rewriteLessThanEqual(LessThanEqual lessThanEqual) { + if (isTimeStampNsDateComparison(lessThanEqual)) { + return rewriteTimeStampNsDateComparison(lessThanEqual); + } if (lessThanEqual.left() instanceof Date) { // V1 if (lessThanEqual.left().child(0).getDataType() instanceof DateTimeType @@ -167,4 +184,15 @@ private static Expression rewriteLessThanEqual(LessThanEqual lessThanEqual) { } return lessThanEqual; } + + private static boolean isTimeStampNsDateComparison(ComparisonPredicate comparison) { + return comparison.left() instanceof Date + && comparison.left().child(0).getDataType() instanceof TimeStampNsType + && comparison.right() instanceof DateLiteral; + } + + private static Expression rewriteTimeStampNsDateComparison(ComparisonPredicate comparison) { + return SimplifyComparisonPredicate.processDateTimeLikeComparisonPredicateDateLiteral( + comparison, comparison.left().child(0), (DateLiteral) comparison.right()); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnBE.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnBE.java index 3f6812405e864b..e847d4b97af035 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnBE.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnBE.java @@ -68,6 +68,7 @@ import org.apache.doris.nereids.trees.expressions.literal.SmallIntLiteral; import org.apache.doris.nereids.trees.expressions.literal.StringLiteral; import org.apache.doris.nereids.trees.expressions.literal.StructLiteral; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral; import org.apache.doris.nereids.types.ArrayType; import org.apache.doris.nereids.types.DataType; @@ -76,6 +77,7 @@ import org.apache.doris.nereids.types.MapType; import org.apache.doris.nereids.types.StructField; import org.apache.doris.nereids.types.StructType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.proto.InternalService; import org.apache.doris.proto.InternalService.PConstantExprResult; import org.apache.doris.proto.Types.PScalarType; @@ -107,6 +109,7 @@ import java.time.DateTimeException; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.ZoneOffset; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -125,6 +128,7 @@ public class FoldConstantRuleOnBE implements ExpressionPatternRuleFactory { public static final FoldConstantRuleOnBE INSTANCE = new FoldConstantRuleOnBE(); private static final Logger LOG = LogManager.getLogger(FoldConstantRuleOnBE.class); + private static final long NANOS_PER_SECOND = 1_000_000_000L; @Override public List> buildRules() { @@ -471,6 +475,15 @@ public static List getResultExpression(DataType type, PValues resultCon Literal literal = new DecimalV3Literal(decimalV3Type, bigDecimal); res.add(literal); } + } else if (type instanceof TimeStampNsType) { + // TIMESTAMP_NS crosses the BE-folding protobuf boundary as signed epoch nanoseconds. + // Keep it separate from DATETIMEV2, whose uint64 payload uses packed civil fields. + int num = resultContent.getInt64ValueCount(); + for (int i = 0; i < num; ++i) { + LocalDateTime dateTime = convertEpochNanosToJavaDateTime( + resultContent.getInt64Value(i)); + res.add(TimeStampNsLiteral.fromJavaDateType(dateTime)); + } } else if (type.isDateTimeV2Type()) { int num = resultContent.getUint64ValueCount(); for (int i = 0; i < num; ++i) { @@ -688,6 +701,12 @@ private static LocalDateTime convertToJavaDateTimeV2(long time) { } } + private static LocalDateTime convertEpochNanosToJavaDateTime(long epochNanos) { + long epochSecond = Math.floorDiv(epochNanos, NANOS_PER_SECOND); + int nanoOfSecond = (int) Math.floorMod(epochNanos, NANOS_PER_SECOND); + return LocalDateTime.ofEpochSecond(epochSecond, nanoOfSecond, ZoneOffset.UTC); + } + private static LocalDate convertToJavaDateV2(int date) { int year = date >> 9; int month = (date >> 5) & 0XF; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java index 5338bf7df9b2ef..2e24955ce29ab9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java @@ -519,7 +519,8 @@ public Expression visitCast(Cast cast, ExpressionRewriteContext context) { // } try { // TODO: support no throw exception in `checkedCastTo` and return Optional - if (cast.child().getDataType().isStringLikeType() && dataType.isComplexType()) { + if ((dataType.isVariantType() && cast.child().getDataType().isTimeStampNsType()) + || (cast.child().getDataType().isStringLikeType() && dataType.isComplexType())) { return cast; } Expression castResult = child.checkedCastTo(dataType); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/PredicateRewriteForPartitionPrune.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/PredicateRewriteForPartitionPrune.java index d43734dac492fb..dcb56056a96d48 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/PredicateRewriteForPartitionPrune.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/PredicateRewriteForPartitionPrune.java @@ -19,6 +19,7 @@ import org.apache.doris.nereids.CascadesContext; import org.apache.doris.nereids.trees.expressions.And; +import org.apache.doris.nereids.trees.expressions.EqualTo; import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.expressions.GreaterThanEqual; import org.apache.doris.nereids.trees.expressions.InPredicate; @@ -26,13 +27,16 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.Date; import org.apache.doris.nereids.trees.expressions.literal.DateLiteral; import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionRewriter; import org.apache.doris.nereids.types.DateTimeType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.util.ExpressionUtils; import java.util.ArrayList; import java.util.List; +import java.util.Optional; /** rewrite predicate for partition prune @@ -45,7 +49,7 @@ public static Expression rewrite(Expression expression, return expression.accept(rewriter, cascadesContext); } - /* F: a DateTime or DateTimeV2 column + /* F: a DateTime, DateTimeV2, or TimeStampNs column * Date(F) in (2020-01-02, 2020-01-01) => * (2020-01-01 24:00:00 >= F >= 2020-01-01 00:00:00) * or (2020-01-02 24:00:00 >= F >= 2020-01-02 00:00:00) @@ -87,9 +91,54 @@ public Expression visitInPredicate(InPredicate in, CascadesContext context) { if (convertable) { return ExpressionUtils.or(splitIn); } + } else if (dateChild.getDataType() instanceof TimeStampNsType) { + for (Expression opt : in.getOptions()) { + Optional range = timestampNsDateRange(dateChild, opt); + if (!range.isPresent()) { + convertable = false; + break; + } + splitIn.add(range.get()); + } + if (convertable) { + return ExpressionUtils.or(splitIn); + } } } return in; } + @Override + public Expression visitEqualTo(EqualTo equalTo, CascadesContext context) { + if (equalTo.left() instanceof Date) { + Expression dateChild = equalTo.left().child(0); + if (dateChild.getDataType() instanceof TimeStampNsType) { + return timestampNsDateRange(dateChild, equalTo.right()).orElse(equalTo); + } + } + return equalTo; + } + + private static Optional timestampNsDateRange(Expression dateChild, Expression option) { + if (!(option instanceof DateV2Literal)) { + return Optional.empty(); + } + DateV2Literal date = (DateV2Literal) option; + TimeStampNsLiteral minValue = TimeStampNsLiteral.getMinValue(); + TimeStampNsLiteral maxValue = TimeStampNsLiteral.getMaxValue(); + DateV2Literal minDate = new DateV2Literal( + minValue.getYear(), minValue.getMonth(), minValue.getDay()); + DateV2Literal maxDate = new DateV2Literal( + maxValue.getYear(), maxValue.getMonth(), maxValue.getDay()); + if (date.compareTo(minDate) < 0 || date.compareTo(maxDate) > 0) { + return Optional.empty(); + } + TimeStampNsLiteral begin = date.equals(minDate) ? minValue : new TimeStampNsLiteral( + date.getYear(), date.getMonth(), date.getDay(), 0, 0, 0, 0); + TimeStampNsLiteral end = date.equals(maxDate) ? maxValue : TimeStampNsLiteral.createEndOfDay( + date.getYear(), date.getMonth(), date.getDay()); + return Optional.of(new And(new GreaterThanEqual(dateChild, begin), + new LessThanEqual(dateChild, end))); + } + } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/RewriteDefaultExpression.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/RewriteDefaultExpression.java index 6dc8ab7c72ccce..1537f1fc387480 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/RewriteDefaultExpression.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/RewriteDefaultExpression.java @@ -31,8 +31,10 @@ import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.expressions.SlotReference; import org.apache.doris.nereids.trees.expressions.literal.NullLiteral; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; import org.apache.doris.nereids.types.DataType; +import org.apache.doris.nereids.util.TimestampNsDefaultValueUtils; import org.apache.doris.nereids.util.TypeCoercionUtils; import com.google.common.collect.ImmutableList; @@ -92,6 +94,12 @@ private static Expression rewrite(ExpressionMatchingContext context) { } } + Optional timestampNsDefault + = TimestampNsDefaultValueUtils.currentTimestampLiteral(column); + if (timestampNsDefault.isPresent()) { + return timestampNsDefault.get(); + } + Expression defaultValueExpr = new NereidsParser().parseExpression(defaultValueSql); if (defaultValueExpr instanceof UnboundFunction) { CascadesContext cascadesContext = context.cascadesContext; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicate.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicate.java index 335fe78307180f..d4d7b0a246304f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicate.java @@ -48,6 +48,7 @@ import org.apache.doris.nereids.trees.expressions.literal.Literal; import org.apache.doris.nereids.trees.expressions.literal.NumericLiteral; import org.apache.doris.nereids.trees.expressions.literal.SmallIntLiteral; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral; import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DataType; @@ -58,6 +59,7 @@ import org.apache.doris.nereids.types.DecimalV3Type; import org.apache.doris.nereids.types.IntegerType; import org.apache.doris.nereids.types.SmallIntType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TinyIntType; import org.apache.doris.nereids.types.coercion.DateLikeType; import org.apache.doris.nereids.types.coercion.IntegralType; @@ -181,8 +183,13 @@ private static Expression processDateLikeTypeCoercion(ComparisonPredicate cp, Ex && ((Cast) left).getDataType().equals(right.getDataType())) { Cast cast = (Cast) left; if (cast.child().getDataType() instanceof DateTimeType - || cast.child().getDataType() instanceof DateTimeV2Type) { + || cast.child().getDataType() instanceof DateTimeV2Type + || cast.child().getDataType() instanceof TimeStampNsType) { // right is datetime + if (right instanceof TimeStampNsLiteral) { + return processDateTimeLikeComparisonPredicateTimeStampNsLiteral( + cp, cast.child(), (TimeStampNsLiteral) right); + } if (right instanceof DateTimeV2Literal) { return processDateTimeLikeComparisonPredicateDateTimeV2Literal( cp, cast.child(), (DateTimeV2Literal) right); @@ -203,6 +210,40 @@ private static Expression processDateLikeTypeCoercion(ComparisonPredicate cp, Ex return cp; } + private static Expression processDateTimeLikeComparisonPredicateTimeStampNsLiteral( + ComparisonPredicate comparisonPredicate, Expression left, TimeStampNsLiteral right) { + DataType leftType = left.getDataType(); + if (leftType instanceof TimeStampNsType) { + return comparisonPredicate; + } + if (!(leftType instanceof DateTimeType) && !(leftType instanceof DateTimeV2Type)) { + return comparisonPredicate; + } + int toScale = leftType instanceof DateTimeV2Type ? ((DateTimeV2Type) leftType).getScale() : 0; + if (toScale >= TimeStampNsType.SCALE) { + return comparisonPredicate; + } + + DateTimeV2Literal rounded; + if (comparisonPredicate instanceof EqualTo || comparisonPredicate instanceof NullSafeEqual) { + rounded = right.roundFloorToDateTimeV2(toScale); + if (rounded.getNanoSecond() != right.getNanoSecond()) { + return comparisonPredicate instanceof NullSafeEqual + ? BooleanLiteral.FALSE : ExpressionUtils.falseOrNull(left); + } + } else if (comparisonPredicate instanceof GreaterThan + || comparisonPredicate instanceof LessThanEqual) { + rounded = right.roundFloorToDateTimeV2(toScale); + } else if (comparisonPredicate instanceof LessThan + || comparisonPredicate instanceof GreaterThanEqual) { + rounded = right.roundCeilingToDateTimeV2(toScale); + } else { + return comparisonPredicate; + } + Expression newRight = leftType instanceof DateTimeType ? migrateToDateTime(rounded) : rounded; + return comparisonPredicate.withChildren(left, newRight); + } + // process cast(datetime as datetime) cmp datetime private static Expression processDateTimeLikeComparisonPredicateDateTimeV2Literal( ComparisonPredicate comparisonPredicate, Expression left, DateTimeV2Literal right) { @@ -214,9 +255,9 @@ private static Expression processDateTimeLikeComparisonPredicateDateTimeV2Litera DateTimeV2Type rightType = right.getDataType(); if (toScale < rightType.getScale()) { if (comparisonPredicate instanceof EqualTo) { - long originValue = right.getMicroSecond(); + long originValue = right.getNanoSecond(); right = right.roundFloor(toScale); - if (right.getMicroSecond() != originValue) { + if (right.getNanoSecond() != originValue) { // TODO: the ideal way is to return an If expr like: // return new If(new IsNull(left), new NullLiteral(BooleanType.INSTANCE), // BooleanLiteral.of(false)); @@ -226,9 +267,9 @@ private static Expression processDateTimeLikeComparisonPredicateDateTimeV2Litera return ExpressionUtils.falseOrNull(left); } } else if (comparisonPredicate instanceof NullSafeEqual) { - long originValue = right.getMicroSecond(); + long originValue = right.getNanoSecond(); right = right.roundFloor(toScale); - if (right.getMicroSecond() != originValue) { + if (right.getNanoSecond() != originValue) { return BooleanLiteral.of(false); } } else if (comparisonPredicate instanceof GreaterThan @@ -274,31 +315,54 @@ private static Expression processDateTimeLikeComparisonPredicateDateTimeV2Litera } // process cast(datetime as date) cmp date - private static Expression processDateTimeLikeComparisonPredicateDateLiteral( + static Expression processDateTimeLikeComparisonPredicateDateLiteral( ComparisonPredicate comparisonPredicate, Expression left, DateLiteral right) { DataType leftType = left.getDataType(); - if (!(leftType instanceof DateTimeType) && !(leftType instanceof DateTimeV2Type)) { + if (!(leftType instanceof DateTimeType) && !(leftType instanceof DateTimeV2Type) + && !(leftType instanceof TimeStampNsType)) { return comparisonPredicate; } if (right instanceof DateTimeLiteral) { return comparisonPredicate; } - DateTimeLiteral lowBound = null; - DateTimeLiteral upBound = null; + DateLiteral lowBound; + DateLiteral upBound; if (leftType instanceof DateTimeType) { lowBound = new DateTimeLiteral(right.getYear(), right.getMonth(), right.getDay(), 0, 0, 0); upBound = new DateTimeLiteral(right.getYear(), right.getMonth(), right.getDay(), 23, 59, 59); + } else if (leftType instanceof TimeStampNsType) { + // TIMESTAMP_NS has fixed scale 9 and an Int64 epoch-nanosecond range. Its boundary + // dates are only partially representable, so a whole-day rewrite must use the exact + // type bounds instead of constructing an invalid midnight or end-of-day literal. + TimeStampNsLiteral minValue = TimeStampNsLiteral.getMinValue(); + TimeStampNsLiteral maxValue = TimeStampNsLiteral.getMaxValue(); + DateV2Literal minDate = new DateV2Literal( + minValue.getYear(), minValue.getMonth(), minValue.getDay()); + DateV2Literal maxDate = new DateV2Literal( + maxValue.getYear(), maxValue.getMonth(), maxValue.getDay()); + int compareToMin = right.compareTo(minDate); + int compareToMax = right.compareTo(maxDate); + if (compareToMin < 0 || compareToMax > 0) { + return simplifyDateComparisonOutsideRange( + comparisonPredicate, left, compareToMin < 0); + } + lowBound = compareToMin == 0 ? minValue : new TimeStampNsLiteral( + right.getYear(), right.getMonth(), right.getDay(), 0, 0, 0, 0); + upBound = compareToMax == 0 ? maxValue : TimeStampNsLiteral.createEndOfDay( + right.getYear(), right.getMonth(), right.getDay()); } else { - long upMicroSecond = 0; - for (int i = 0; i < ((DateTimeV2Type) leftType).getScale(); i++) { - upMicroSecond = 10 * upMicroSecond + 9; + DateTimeV2Type dateTimeV2Type = (DateTimeV2Type) leftType; + long upperFraction = 0; + for (int i = 0; i < dateTimeV2Type.getScale(); i++) { + upperFraction = 10 * upperFraction + 9; } - upMicroSecond *= (int) Math.pow(10, 6 - ((DateTimeV2Type) leftType).getScale()); - lowBound = new DateTimeV2Literal((DateTimeV2Type) leftType, + int scale = dateTimeV2Type.getScale(); + upperFraction *= (long) Math.pow(10, DateTimeV2Type.MAX_SCALE - scale); + lowBound = new DateTimeV2Literal(dateTimeV2Type, right.getYear(), right.getMonth(), right.getDay(), 0, 0, 0, 0); - upBound = new DateTimeV2Literal((DateTimeV2Type) leftType, - right.getYear(), right.getMonth(), right.getDay(), 23, 59, 59, upMicroSecond); + upBound = new DateTimeV2Literal(dateTimeV2Type, + right.getYear(), right.getMonth(), right.getDay(), 23, 59, 59, upperFraction); } if (comparisonPredicate instanceof GreaterThanEqual || comparisonPredicate instanceof LessThan) { @@ -321,17 +385,43 @@ private static Expression processDateTimeLikeComparisonPredicateDateLiteral( return comparisonPredicate; } + /** + * Simplify a date/datetime comparison whose right literal is outside the range representable by + * the left expression. For every non-null left value, the result is constant and depends only on + * the comparison direction and whether the literal is below the minimum or above the maximum. + * Null-safe equality is always false; other predicates return true-or-null or false-or-null to + * preserve SQL three-valued logic when the left expression is nullable. + * + * @param comparisonPredicate comparison to simplify + * @param left left expression whose type defines the representable range + * @param rightBeforeMin true if the right literal is below that range; false if it is above + * @return the constant-equivalent expression with the original NULL semantics + */ + private static Expression simplifyDateComparisonOutsideRange( + ComparisonPredicate comparisonPredicate, Expression left, boolean rightBeforeMin) { + if (comparisonPredicate instanceof NullSafeEqual) { + return BooleanLiteral.FALSE; + } + if (comparisonPredicate instanceof EqualTo) { + return ExpressionUtils.falseOrNull(left); + } + boolean alwaysTrue = rightBeforeMin + ? comparisonPredicate instanceof GreaterThan || comparisonPredicate instanceof GreaterThanEqual + : comparisonPredicate instanceof LessThan || comparisonPredicate instanceof LessThanEqual; + return alwaysTrue ? ExpressionUtils.trueOrNull(left) : ExpressionUtils.falseOrNull(left); + } + // process cast(date as datetime/date) cmp datetime/date private static Expression processDateLikeComparisonPredicateDateLiteral( ComparisonPredicate comparisonPredicate, Expression left, DateLiteral right) { if (!(left.getDataType() instanceof DateType) && !(left.getDataType() instanceof DateV2Type)) { return comparisonPredicate; } - if (right instanceof DateTimeLiteral) { - DateTimeLiteral dateTimeLiteral = (DateTimeLiteral) right; - right = migrateToDateV2(dateTimeLiteral); - if (dateTimeLiteral.getHour() != 0 || dateTimeLiteral.getMinute() != 0 - || dateTimeLiteral.getSecond() != 0 || dateTimeLiteral.getMicroSecond() != 0) { + if (right.getDataType().isDateTimeType() || right.getDataType().isDateTimeV2Type() + || right.getDataType().isTimeStampNsType() || right.getDataType().isTimeStampTzType()) { + boolean isMidnight = right.isMidnight(); + right = new DateV2Literal(right.getYear(), right.getMonth(), right.getDay()); + if (!isMidnight) { if (comparisonPredicate instanceof EqualTo) { return ExpressionUtils.falseOrNull(left); } else if (comparisonPredicate instanceof NullSafeEqual) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyInPredicate.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyInPredicate.java index b66db8e66f0d03..2ca52c64de406c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyInPredicate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyInPredicate.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.literal.DateTimeV2Literal; import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.util.DateUtils; import com.google.common.collect.ImmutableList; @@ -93,7 +94,7 @@ && canLosslessConvertToLowScaleLiteral( */ private static boolean canLosslessConvertToDateV2Literal(DateTimeV2Literal literal) { return (literal.getHour() | literal.getMinute() | literal.getSecond() - | literal.getMicroSecond()) == 0L; + | literal.getNanoSecond()) == 0L; } private static DateV2Literal convertToDateV2Literal(DateTimeV2Literal literal) { @@ -101,7 +102,7 @@ private static DateV2Literal convertToDateV2Literal(DateTimeV2Literal literal) { } private static boolean canLosslessConvertToLowScaleLiteral(DateTimeV2Literal literal, int targetScale) { - long scaleFactor = (long) Math.pow(10, DateTimeV2Type.MAX_SCALE - targetScale); - return literal.getMicroSecond() % scaleFactor == 0; + long scaleFactor = (long) Math.pow(10, DateUtils.NANOSECOND_SCALE - targetScale); + return literal.getNanoSecond() % scaleFactor == 0; } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PushDownVirtualColumnsIntoOlapScan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PushDownVirtualColumnsIntoOlapScan.java index 4c60a9dade30c4..720fce3b3ea2f6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PushDownVirtualColumnsIntoOlapScan.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PushDownVirtualColumnsIntoOlapScan.java @@ -59,6 +59,7 @@ import org.apache.doris.nereids.types.LargeIntType; import org.apache.doris.nereids.types.SmallIntType; import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TinyIntType; import org.apache.doris.nereids.types.VarcharType; import org.apache.doris.nereids.util.ExpressionUtils; @@ -144,6 +145,7 @@ public class PushDownVirtualColumnsIntoOlapScan implements RewriteRuleFactory { DateV2Type.class, DateTimeType.class, DateTimeV2Type.class, + TimeStampNsType.class, FloatType.class, DoubleType.class, CharType.class, diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/stats/FilterEstimation.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/stats/FilterEstimation.java index 482f7872be6015..c14628ca3b0b14 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/stats/FilterEstimation.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/stats/FilterEstimation.java @@ -21,6 +21,7 @@ import org.apache.doris.analysis.DateLiteralUtils; import org.apache.doris.analysis.LiteralExpr; import org.apache.doris.analysis.StringLiteral; +import org.apache.doris.analysis.TimeStampNsLiteral; import org.apache.doris.nereids.stats.FilterEstimation.EstimationContext; import org.apache.doris.nereids.trees.expressions.And; import org.apache.doris.nereids.trees.expressions.ComparisonPredicate; @@ -475,7 +476,7 @@ private Statistics estimateColumnToConstant(ComparisonPredicate cp, EstimationCo return estimateColumnEqualToConstant(cp, statsForLeft, statsForRight, context); } else { // literal Map used to covert dateLiteral back to stringLiteral - Map literalMap = new HashMap<>(); + Map literalMap = new HashMap<>(); DataType compareType = cp.left().getDataType(); Optional statsForLeftMayConvertedOpt = tryConvertStringColStatsToDateColStats(statsForLeft, literalMap); @@ -523,7 +524,7 @@ private Statistics estimateColumnToConstant(ComparisonPredicate cp, EstimationCo } private ColumnStatistic convertDateColStatsToStringColStats(ColumnStatistic colStats, - Map literalMap) { + Map literalMap) { ColumnStatisticBuilder builder = new ColumnStatisticBuilder(colStats); if (colStats.minExpr != null) { builder.setMinExpr(literalMap.get(colStats.minExpr)) @@ -553,18 +554,18 @@ private ColumnStatistic convertDateColStatsToStringColStats(ColumnStatistic colS } private Optional tryConvertStringColStatsToDateColStats(ColumnStatistic colStats, - Map literalMap) { + Map literalMap) { if (colStats.minExpr == null || colStats.maxExpr == null) { return Optional.empty(); } if (!(colStats.minExpr instanceof StringLiteral) || !(colStats.maxExpr instanceof StringLiteral)) { return Optional.empty(); } - Optional newMinExpr = tryConvertStrLiteralToDateLiteral(colStats.minExpr); + Optional newMinExpr = tryConvertStrLiteralToDateLiteral(colStats.minExpr); if (!newMinExpr.isPresent()) { return Optional.empty(); } - Optional newMaxExpr = tryConvertStrLiteralToDateLiteral(colStats.maxExpr); + Optional newMaxExpr = tryConvertStrLiteralToDateLiteral(colStats.maxExpr); if (!newMaxExpr.isPresent()) { return Optional.empty(); } @@ -578,7 +579,10 @@ private Optional tryConvertStringColStatsToDateColStats(ColumnS if (colStats.hotValues != null) { for (Literal oneHot : colStats.hotValues.keySet()) { try { - DateTimeLiteral oneHotDate = new DateTimeLiteral(oneHot.getStringValue()); + Literal oneHotDate = newMinExpr.get().getType().isTimeStampNs() + ? new org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral( + oneHot.getStringValue()) + : new DateTimeLiteral(oneHot.getStringValue()); newHotValues.put(oneHotDate, colStats.hotValues.get(oneHot)); } catch (Exception e) { @@ -588,15 +592,15 @@ private Optional tryConvertStringColStatsToDateColStats(ColumnS } ColumnStatisticBuilder builder = new ColumnStatisticBuilder(colStats); - return Optional.of(builder.setMinValue(newMinExpr.get().getDoubleValueAsDateTime()) + return Optional.of(builder.setMinValue(getDoubleValueAsDateTime(newMinExpr.get())) .setMinExpr(newMinExpr.get()) - .setMaxValue(newMaxExpr.get().getDoubleValueAsDateTime()) + .setMaxValue(getDoubleValueAsDateTime(newMaxExpr.get())) .setMaxExpr(newMaxExpr.get()) .setHotValues(newHotValues.isEmpty() ? null : newHotValues) .build()); } - private Optional tryConvertStrLiteralToDateLiteral(LiteralExpr literal) { + private Optional tryConvertStrLiteralToDateLiteral(LiteralExpr literal) { if (literal == null) { return Optional.empty(); } @@ -604,9 +608,9 @@ private Optional tryConvertStrLiteralToDateLiteral(LiteralExpr lite return Optional.empty(); } - DateLiteral dt = null; + LiteralExpr dt = null; try { - dt = DateLiteralUtils.createDateLiteral(literal.getStringValue(), null); + dt = DateLiteralUtils.createLiteral(literal.getStringValue(), null); dt.checkValueValid(); } catch (Exception e) { // ignore @@ -614,6 +618,15 @@ private Optional tryConvertStrLiteralToDateLiteral(LiteralExpr lite return dt == null ? Optional.empty() : Optional.of(dt); } + private double getDoubleValueAsDateTime(LiteralExpr literal) { + if (literal instanceof DateLiteral) { + return ((DateLiteral) literal).getDoubleValueAsDateTime(); + } + Preconditions.checkState(literal instanceof TimeStampNsLiteral, + "Expected a date-like literal, but got %s", literal.getClass()); + return ((TimeStampNsLiteral) literal).getDoubleValueAsDateTime(); + } + private Statistics estimateColumnEqualToConstant(ComparisonPredicate cp, ColumnStatistic statsForLeft, ColumnStatistic statsForRight, EstimationContext context) { double selectivity = DEFAULT_ISNULL_SELECTIVITY; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Cast.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Cast.java index 6c21d431ebc105..61903e06f8047b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Cast.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Cast.java @@ -18,9 +18,11 @@ package org.apache.doris.nereids.trees.expressions; import org.apache.doris.common.util.TimeUtils; +import org.apache.doris.nereids.exceptions.AnalysisException; import org.apache.doris.nereids.exceptions.UnboundException; import org.apache.doris.nereids.trees.expressions.functions.Monotonic; import org.apache.doris.nereids.trees.expressions.literal.Literal; +import org.apache.doris.nereids.trees.expressions.literal.NullLiteral; import org.apache.doris.nereids.trees.expressions.literal.TimestampTzLiteral; import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; @@ -32,6 +34,7 @@ import org.apache.doris.nereids.types.IntegerType; import org.apache.doris.nereids.types.LargeIntType; import org.apache.doris.nereids.types.SmallIntType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.TinyIntType; import org.apache.doris.nereids.types.coercion.DateLikeType; @@ -113,13 +116,18 @@ public static boolean castNullable(boolean srcNullable, DataType srcType, DataTy // StringLike to other type is always nullable. if (childDataType.isStringLikeType() && !targetType.isStringLikeType()) { return true; + } else if ((childDataType.isDateLikeType() || childDataType.isTimeType()) + && targetType instanceof TimeStampNsType) { + // Temporal inputs can fail because TIMESTAMP_NS has a narrower signed epoch-nanos range. + return true; } else if ((childDataType.isDateTimeType() || childDataType.isDateTimeV2Type() || childDataType.isTimeStampTzType()) && (targetType.isDateTimeType() || targetType.isDateTimeV2Type())) { // datetime to datetime is always nullable return true; - } else if (childDataType.isDateTimeV2Type() && targetType.isTimeStampTzType()) { - // Datetime to timestamptz is always nullable + } else if ((childDataType.isDateTimeV2Type() || childDataType.isTimeStampNsType()) + && targetType.isTimeStampTzType()) { + // Datetime and timestamp_ns to timestamptz are always nullable return true; } else if (childDataType.isTimeStampTzType() && targetType.isTimeStampTzType()) { // timestamptz to timestamptz is always nullable @@ -298,6 +306,10 @@ public boolean isMonotonic(Literal lower, Literal upper) { return false; } + if (targetType instanceof TimeStampNsType && !isRangeWithinTimeStampNs(lower, upper)) { + return false; + } + if (childType instanceof TimeStampTzType && targetType instanceof DateTimeV2Type) { return isTimeStampTzToDateTimeV2Monotonic( (TimeStampTzType) childType, (DateTimeV2Type) targetType, lower, upper); @@ -305,6 +317,18 @@ public boolean isMonotonic(Literal lower, Literal upper) { return true; } + private boolean isRangeWithinTimeStampNs(Literal lower, Literal upper) { + if (lower == null || upper == null) { + return false; + } + try { + return !(lower.checkedCastTo(targetType) instanceof NullLiteral) + && !(upper.checkedCastTo(targetType) instanceof NullLiteral); + } catch (AnalysisException e) { + return false; + } + } + private boolean isTimeStampTzToDateTimeV2Monotonic( TimeStampTzType sourceType, DateTimeV2Type destinationType, Literal lower, Literal upper) { ZoneId timeZone; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/SearchSignature.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/SearchSignature.java index 74e9e06f442c52..76900cc2b27e46 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/SearchSignature.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/SearchSignature.java @@ -49,6 +49,7 @@ public class SearchSignature { private final ComputeSignature computeSignature; private final List signatures; private final List arguments; + private final boolean hasTimeStampNsArgument; // param1: signature type // param2: real argument type @@ -61,6 +62,8 @@ private SearchSignature(ComputeSignature computeSignature, this.computeSignature = computeSignature; this.signatures = signatures; this.arguments = arguments; + this.hasTimeStampNsArgument = arguments.stream() + .anyMatch(argument -> argument.getDataType().isTimeStampNsType()); } public static SearchSignature from(ComputeSignature computeSignature, @@ -244,7 +247,7 @@ private Pair nonStrictMatchedCount(FunctionSignature sig, List * - Boolean: whether the signature can successfully match the arguments * - Pair - Integer, Integer: * - First integer: count of string literal coercions performed during matching - * - Second integer: priority score for datetime and timestamptz type preferences + * - Second integer: priority score for temporal literal coercion */ private Pair> doMatchTypes(FunctionSignature sig, List arguments, BiFunction typePredicate) { @@ -255,6 +258,11 @@ private Pair> doMatchTypes(FunctionSignature sig DataType sigArgType = sig.getArgType(i); Expression argument = arguments.get(i); DataType realType = argument.getDataType(); + if (sigArgType.isTimeStampNsType() && !hasTimeStampNsArgument) { + // TIMESTAMP_NS overloads preserve a typed nanosecond argument. They must not + // change the historical binding of character or other temporal input. + return Pair.of(false, Pair.of(stringLiteralCoersionCount, timeZoneCoersionScore)); + } // we need to try to do string literal coercion when search signature. // for example, FUNC_A has two signature FUNC_A(datetime) and FUNC_A(string) // if SQL block is `FUNC_A('2020-02-02 00:00:00')`, we should return signature FUNC_A(datetime). diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceCount.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceCount.java index e4ad5956c1c290..f0cc6fac537082 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceCount.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceCount.java @@ -27,6 +27,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.util.ExpressionUtils; @@ -46,6 +47,8 @@ public class SequenceCount extends NotNullableAggregateFunction .varArgs(StringType.INSTANCE, DateV2Type.INSTANCE, BooleanType.INSTANCE), FunctionSignature.ret(BigIntType.INSTANCE) .varArgs(StringType.INSTANCE, TimeStampTzType.WILDCARD, BooleanType.INSTANCE), + FunctionSignature.ret(BigIntType.INSTANCE) + .varArgs(StringType.INSTANCE, TimeStampNsType.INSTANCE, BooleanType.INSTANCE), FunctionSignature.ret(BigIntType.INSTANCE) .varArgs(StringType.INSTANCE, DateTimeV2Type.WILDCARD, BooleanType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceFunction.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceFunction.java index 3f3b4e53906846..e6f1479f82e19c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceFunction.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceFunction.java @@ -41,7 +41,8 @@ default void checkLegalityBeforeTypeCoercion() { } if (!getArgumentType(1).isDateLikeType()) { throw new AnalysisException("The timestamp params of " + functionName - + " function must be DATE, DATETIME or TIMESTAMPTZ, but it is " + getArgumentType(1)); + + " function must be DATE, DATETIME, TIMESTAMP_NS or TIMESTAMPTZ, but it is " + + getArgumentType(1)); } String pattern = ((StringLikeLiteral) firstArg).getStringValue(); if (!FunctionCallExpr.parsePattern(pattern)) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceMatch.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceMatch.java index c9f15731a196ee..24dc7f8367a4b7 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceMatch.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/SequenceMatch.java @@ -25,6 +25,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.util.ExpressionUtils; @@ -44,6 +45,8 @@ public class SequenceMatch extends NullableAggregateFunction .varArgs(StringType.INSTANCE, DateV2Type.INSTANCE, BooleanType.INSTANCE), FunctionSignature.ret(BooleanType.INSTANCE) .varArgs(StringType.INSTANCE, TimeStampTzType.WILDCARD, BooleanType.INSTANCE), + FunctionSignature.ret(BooleanType.INSTANCE) + .varArgs(StringType.INSTANCE, TimeStampNsType.INSTANCE, BooleanType.INSTANCE), FunctionSignature.ret(BooleanType.INSTANCE) .varArgs(StringType.INSTANCE, DateTimeV2Type.WILDCARD, BooleanType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNWeighted.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNWeighted.java index 9d3152685a4606..010a6f6bdaf65c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNWeighted.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNWeighted.java @@ -36,6 +36,7 @@ import org.apache.doris.nereids.types.LargeIntType; import org.apache.doris.nereids.types.SmallIntType; import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.TinyIntType; import org.apache.doris.nereids.types.VarcharType; @@ -75,6 +76,8 @@ public class TopNWeighted extends NullableAggregateFunction .args(DateV2Type.INSTANCE, BigIntType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(ArrayType.of(TimeStampTzType.WILDCARD)) .args(TimeStampTzType.WILDCARD, BigIntType.INSTANCE, IntegerType.INSTANCE), + FunctionSignature.ret(ArrayType.of(TimeStampNsType.INSTANCE)) + .args(TimeStampNsType.INSTANCE, BigIntType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(ArrayType.of(DateTimeV2Type.WILDCARD)) .args(DateTimeV2Type.WILDCARD, BigIntType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(ArrayType.of(StringType.INSTANCE)) @@ -114,6 +117,11 @@ public class TopNWeighted extends NullableAggregateFunction BigIntType.INSTANCE, IntegerType.INSTANCE, IntegerType.INSTANCE), + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT) + .args(TimeStampNsType.INSTANCE, + BigIntType.INSTANCE, + IntegerType.INSTANCE, + IntegerType.INSTANCE), FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT) .args(DateTimeV2Type.WILDCARD, BigIntType.INSTANCE, diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnel.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnel.java index ef60c0a8c07d31..9f152821c2fef0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnel.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnel.java @@ -29,6 +29,7 @@ import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.util.ExpressionUtils; @@ -48,6 +49,9 @@ public class WindowFunnel extends NullableAggregateFunction FunctionSignature.ret(IntegerType.INSTANCE) .varArgs(BigIntType.INSTANCE, StringType.INSTANCE, TimeStampTzType.WILDCARD, BooleanType.INSTANCE), + FunctionSignature.ret(IntegerType.INSTANCE) + .varArgs(BigIntType.INSTANCE, StringType.INSTANCE, TimeStampNsType.INSTANCE, + BooleanType.INSTANCE), FunctionSignature.ret(IntegerType.INSTANCE) .varArgs(BigIntType.INSTANCE, StringType.INSTANCE, DateTimeV2Type.WILDCARD, BooleanType.INSTANCE) @@ -91,7 +95,7 @@ public void checkLegalityBeforeTypeCoercion() { } if (!getArgumentType(2).isDateLikeType()) { throw new AnalysisException("The 3rd param of " + functionName - + " function must be DATE, DATETIME or TIMESTAMPTZ"); + + " function must be DATE, DATETIME, TIMESTAMP_NS or TIMESTAMPTZ"); } for (int i = 3; i < arity(); i++) { if (!getArgumentType(i).isBooleanType()) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnelV2.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnelV2.java index 697774eb47f4b6..fabca97f7448ed 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnelV2.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/WindowFunnelV2.java @@ -29,6 +29,7 @@ import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.util.ExpressionUtils; @@ -51,6 +52,9 @@ public class WindowFunnelV2 extends NullableAggregateFunction FunctionSignature.ret(IntegerType.INSTANCE) .varArgs(BigIntType.INSTANCE, StringType.INSTANCE, TimeStampTzType.WILDCARD, BooleanType.INSTANCE), + FunctionSignature.ret(IntegerType.INSTANCE) + .varArgs(BigIntType.INSTANCE, StringType.INSTANCE, TimeStampNsType.INSTANCE, + BooleanType.INSTANCE), FunctionSignature.ret(IntegerType.INSTANCE) .varArgs(BigIntType.INSTANCE, StringType.INSTANCE, DateTimeV2Type.WILDCARD, BooleanType.INSTANCE) @@ -100,7 +104,7 @@ public void checkLegalityBeforeTypeCoercion() { } if (!getArgumentType(2).isDateLikeType()) { throw new AnalysisException("The 3rd param of " + functionName - + " function must be DATE, DATETIME or TIMESTAMPTZ"); + + " function must be DATE, DATETIME, TIMESTAMP_NS or TIMESTAMPTZ"); } for (int i = 3; i < arity(); i++) { if (!getArgumentType(i).isBooleanType()) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeArithmetic.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeArithmetic.java index cd12c00df210cf..84f68591c2747a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeArithmetic.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeArithmetic.java @@ -26,9 +26,11 @@ import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal; import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral; import org.apache.doris.nereids.trees.expressions.literal.Interval.TimeUnit; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.trees.expressions.literal.TimeV2Literal; import org.apache.doris.nereids.trees.expressions.literal.TimestampTzLiteral; import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral; +import org.apache.doris.nereids.types.TimeV2Type; import java.util.Arrays; @@ -295,6 +297,17 @@ private static Expression applyInterval(TimestampTzLiteral date, VarcharLiteral return result; } + private static Expression applyInterval(TimeStampNsLiteral date, VarcharLiteral delta, TimeUnit unit, + boolean add) { + if (unit == TimeUnit.YEAR_MONTH) { + long months = parseYearMonthToMonths(delta.getStringValue()); + return date.plusMonths(add ? months : -months); + } + + long micros = parseIntervalToMicros(delta.getStringValue(), unit); + return date.plusMicroSeconds(add ? micros : -micros); + } + /** * datetime arithmetic function date-add. */ @@ -313,6 +326,11 @@ public static Expression dateAdd(TimestampTzLiteral date, IntegerLiteral day) { return daysAdd(date, day); } + @ExecFunction(name = "date_add") + public static Expression dateAdd(TimeStampNsLiteral date, IntegerLiteral day) { + return daysAdd(date, day); + } + /** * datetime arithmetic function day_hour-add. */ @@ -326,6 +344,11 @@ public static Expression dayHourAdd(TimestampTzLiteral date, VarcharLiteral dayH return applyInterval(date, dayHour, TimeUnit.DAY_HOUR, true); } + @ExecFunction(name = "day_hour_add") + public static Expression dayHourAdd(TimeStampNsLiteral date, VarcharLiteral dayHour) { + return applyInterval(date, dayHour, TimeUnit.DAY_HOUR, true); + } + @ExecFunction(name = "day_hour_sub") public static Expression dayHourSub(DateTimeV2Literal date, VarcharLiteral dayHour) { return applyInterval(date, dayHour, TimeUnit.DAY_HOUR, false); @@ -336,6 +359,11 @@ public static Expression dayHourSub(TimestampTzLiteral date, VarcharLiteral dayH return applyInterval(date, dayHour, TimeUnit.DAY_HOUR, false); } + @ExecFunction(name = "day_hour_sub") + public static Expression dayHourSub(TimeStampNsLiteral date, VarcharLiteral dayHour) { + return applyInterval(date, dayHour, TimeUnit.DAY_HOUR, false); + } + /** * datetime arithmetic function minute_second-add. */ @@ -349,6 +377,11 @@ public static Expression minuteSecondAdd(TimestampTzLiteral date, VarcharLiteral return applyInterval(date, minuteSecond, TimeUnit.MINUTE_SECOND, true); } + @ExecFunction(name = "minute_second_add") + public static Expression minuteSecondAdd(TimeStampNsLiteral date, VarcharLiteral minuteSecond) { + return applyInterval(date, minuteSecond, TimeUnit.MINUTE_SECOND, true); + } + @ExecFunction(name = "minute_second_sub") public static Expression minuteSecondSub(DateTimeV2Literal date, VarcharLiteral minuteSecond) { return applyInterval(date, minuteSecond, TimeUnit.MINUTE_SECOND, false); @@ -359,6 +392,11 @@ public static Expression minuteSecondSub(TimestampTzLiteral date, VarcharLiteral return applyInterval(date, minuteSecond, TimeUnit.MINUTE_SECOND, false); } + @ExecFunction(name = "minute_second_sub") + public static Expression minuteSecondSub(TimeStampNsLiteral date, VarcharLiteral minuteSecond) { + return applyInterval(date, minuteSecond, TimeUnit.MINUTE_SECOND, false); + } + /** * datetime arithmetic function second_microsecond-add. */ @@ -372,6 +410,11 @@ public static Expression secondMicrosecondAdd(TimestampTzLiteral date, VarcharLi return applyInterval(date, secondMicrosecond, TimeUnit.SECOND_MICROSECOND, true); } + @ExecFunction(name = "second_microsecond_add") + public static Expression secondMicrosecondAdd(TimeStampNsLiteral date, VarcharLiteral secondMicrosecond) { + return applyInterval(date, secondMicrosecond, TimeUnit.SECOND_MICROSECOND, true); + } + @ExecFunction(name = "second_microsecond_sub") public static Expression secondMicrosecondSub(DateTimeV2Literal date, VarcharLiteral secondMicrosecond) { return applyInterval(date, secondMicrosecond, TimeUnit.SECOND_MICROSECOND, false); @@ -382,6 +425,11 @@ public static Expression secondMicrosecondSub(TimestampTzLiteral date, VarcharLi return applyInterval(date, secondMicrosecond, TimeUnit.SECOND_MICROSECOND, false); } + @ExecFunction(name = "second_microsecond_sub") + public static Expression secondMicrosecondSub(TimeStampNsLiteral date, VarcharLiteral secondMicrosecond) { + return applyInterval(date, secondMicrosecond, TimeUnit.SECOND_MICROSECOND, false); + } + /** * datetime arithmetic function date-sub. */ @@ -400,6 +448,11 @@ public static Expression dateSub(TimestampTzLiteral date, IntegerLiteral day) { return dateAdd(date, new IntegerLiteral(-day.getValue())); } + @ExecFunction(name = "date_sub") + public static Expression dateSub(TimeStampNsLiteral date, IntegerLiteral day) { + return dateAdd(date, new IntegerLiteral(-day.getValue())); + } + /** * datetime arithmetic function years-add. */ @@ -418,6 +471,11 @@ public static Expression yearsAdd(TimestampTzLiteral date, IntegerLiteral year) return date.plusYears(year.getValue()); } + @ExecFunction(name = "years_add") + public static Expression yearsAdd(TimeStampNsLiteral date, IntegerLiteral year) { + return date.plusYears(year.getValue()); + } + /** * datetime arithmetic function quarters-add. */ @@ -436,6 +494,11 @@ public static Expression quartersAdd(TimestampTzLiteral date, IntegerLiteral qua return date.plusMonths(3 * quarter.getValue()); } + @ExecFunction(name = "quarters_add") + public static Expression quartersAdd(TimeStampNsLiteral date, IntegerLiteral quarter) { + return date.plusMonths(3 * quarter.getValue()); + } + /** * datetime arithmetic function months-add. */ @@ -454,6 +517,11 @@ public static Expression monthsAdd(TimestampTzLiteral date, IntegerLiteral month return date.plusMonths(month.getValue()); } + @ExecFunction(name = "months_add") + public static Expression monthsAdd(TimeStampNsLiteral date, IntegerLiteral month) { + return date.plusMonths(month.getValue()); + } + /** * datetime arithmetic function weeks-add. */ @@ -472,6 +540,11 @@ public static Expression weeksAdd(TimestampTzLiteral date, IntegerLiteral weeks) return date.plusWeeks(weeks.getValue()); } + @ExecFunction(name = "weeks_add") + public static Expression weeksAdd(TimeStampNsLiteral date, IntegerLiteral weeks) { + return date.plusWeeks(weeks.getValue()); + } + /** * datetime arithmetic function days-add. */ @@ -490,6 +563,11 @@ public static Expression daysAdd(TimestampTzLiteral date, IntegerLiteral day) { return date.plusDays(day.getValue()); } + @ExecFunction(name = "days_add") + public static Expression daysAdd(TimeStampNsLiteral date, IntegerLiteral day) { + return date.plusDays(day.getValue()); + } + /** * datetime arithmetic function day_second-add. */ @@ -503,6 +581,11 @@ public static Expression daysAdd(TimestampTzLiteral date, VarcharLiteral daySeco return applyInterval(date, daySecond, TimeUnit.DAY_SECOND, true); } + @ExecFunction(name = "day_second_add") + public static Expression daysAdd(TimeStampNsLiteral date, VarcharLiteral daySecond) { + return applyInterval(date, daySecond, TimeUnit.DAY_SECOND, true); + } + @ExecFunction(name = "day_second_sub") public static Expression daysSub(DateTimeV2Literal date, VarcharLiteral daySecond) { return applyInterval(date, daySecond, TimeUnit.DAY_SECOND, false); @@ -513,6 +596,11 @@ public static Expression daysSub(TimestampTzLiteral date, VarcharLiteral daySeco return applyInterval(date, daySecond, TimeUnit.DAY_SECOND, false); } + @ExecFunction(name = "day_second_sub") + public static Expression daysSub(TimeStampNsLiteral date, VarcharLiteral daySecond) { + return applyInterval(date, daySecond, TimeUnit.DAY_SECOND, false); + } + /** * datetime arithmetic function days-sub */ @@ -531,6 +619,11 @@ public static Expression daysSub(TimestampTzLiteral date, IntegerLiteral day) { return daysAdd(date, new IntegerLiteral(-day.getValue())); } + @ExecFunction(name = "days_sub") + public static Expression daysSub(TimeStampNsLiteral date, IntegerLiteral day) { + return daysAdd(date, new IntegerLiteral(-day.getValue())); + } + @ExecFunction(name = "day_minute_add") public static Expression dayMinuteAdd(DateTimeV2Literal date, VarcharLiteral dayMinute) { return applyInterval(date, dayMinute, TimeUnit.DAY_MINUTE, true); @@ -541,6 +634,11 @@ public static Expression dayMinuteAdd(TimestampTzLiteral date, VarcharLiteral da return applyInterval(date, dayMinute, TimeUnit.DAY_MINUTE, true); } + @ExecFunction(name = "day_minute_add") + public static Expression dayMinuteAdd(TimeStampNsLiteral date, VarcharLiteral dayMinute) { + return applyInterval(date, dayMinute, TimeUnit.DAY_MINUTE, true); + } + @ExecFunction(name = "day_minute_sub") public static Expression dayMinuteSub(DateTimeV2Literal date, VarcharLiteral dayMinute) { return applyInterval(date, dayMinute, TimeUnit.DAY_MINUTE, false); @@ -551,6 +649,11 @@ public static Expression dayMinuteSub(TimestampTzLiteral date, VarcharLiteral da return applyInterval(date, dayMinute, TimeUnit.DAY_MINUTE, false); } + @ExecFunction(name = "day_minute_sub") + public static Expression dayMinuteSub(TimeStampNsLiteral date, VarcharLiteral dayMinute) { + return applyInterval(date, dayMinute, TimeUnit.DAY_MINUTE, false); + } + @ExecFunction(name = "day_microsecond_add") public static Expression dayMicrosecondAdd(DateTimeV2Literal date, VarcharLiteral dayMicrosecond) { return applyInterval(date, dayMicrosecond, TimeUnit.DAY_MICROSECOND, true); @@ -561,6 +664,11 @@ public static Expression dayMicrosecondAdd(TimestampTzLiteral date, VarcharLiter return applyInterval(date, dayMicrosecond, TimeUnit.DAY_MICROSECOND, true); } + @ExecFunction(name = "day_microsecond_add") + public static Expression dayMicrosecondAdd(TimeStampNsLiteral date, VarcharLiteral dayMicrosecond) { + return applyInterval(date, dayMicrosecond, TimeUnit.DAY_MICROSECOND, true); + } + @ExecFunction(name = "day_microsecond_sub") public static Expression dayMicrosecondSub(DateTimeV2Literal date, VarcharLiteral dayMicrosecond) { return applyInterval(date, dayMicrosecond, TimeUnit.DAY_MICROSECOND, false); @@ -571,6 +679,11 @@ public static Expression dayMicrosecondSub(TimestampTzLiteral date, VarcharLiter return applyInterval(date, dayMicrosecond, TimeUnit.DAY_MICROSECOND, false); } + @ExecFunction(name = "day_microsecond_sub") + public static Expression dayMicrosecondSub(TimeStampNsLiteral date, VarcharLiteral dayMicrosecond) { + return applyInterval(date, dayMicrosecond, TimeUnit.DAY_MICROSECOND, false); + } + @ExecFunction(name = "hour_minute_add") public static Expression hourMinuteAdd(DateTimeV2Literal date, VarcharLiteral hourMinute) { return applyInterval(date, hourMinute, TimeUnit.HOUR_MINUTE, true); @@ -581,6 +694,11 @@ public static Expression hourMinuteAdd(TimestampTzLiteral date, VarcharLiteral h return applyInterval(date, hourMinute, TimeUnit.HOUR_MINUTE, true); } + @ExecFunction(name = "hour_minute_add") + public static Expression hourMinuteAdd(TimeStampNsLiteral date, VarcharLiteral hourMinute) { + return applyInterval(date, hourMinute, TimeUnit.HOUR_MINUTE, true); + } + @ExecFunction(name = "hour_minute_sub") public static Expression hourMinuteSub(DateTimeV2Literal date, VarcharLiteral hourMinute) { return applyInterval(date, hourMinute, TimeUnit.HOUR_MINUTE, false); @@ -591,6 +709,11 @@ public static Expression hourMinuteSub(TimestampTzLiteral date, VarcharLiteral h return applyInterval(date, hourMinute, TimeUnit.HOUR_MINUTE, false); } + @ExecFunction(name = "hour_minute_sub") + public static Expression hourMinuteSub(TimeStampNsLiteral date, VarcharLiteral hourMinute) { + return applyInterval(date, hourMinute, TimeUnit.HOUR_MINUTE, false); + } + @ExecFunction(name = "hour_second_add") public static Expression hourSecondAdd(DateTimeV2Literal date, VarcharLiteral hourSecond) { return applyInterval(date, hourSecond, TimeUnit.HOUR_SECOND, true); @@ -601,6 +724,11 @@ public static Expression hourSecondAdd(TimestampTzLiteral date, VarcharLiteral h return applyInterval(date, hourSecond, TimeUnit.HOUR_SECOND, true); } + @ExecFunction(name = "hour_second_add") + public static Expression hourSecondAdd(TimeStampNsLiteral date, VarcharLiteral hourSecond) { + return applyInterval(date, hourSecond, TimeUnit.HOUR_SECOND, true); + } + @ExecFunction(name = "hour_second_sub") public static Expression hourSecondSub(DateTimeV2Literal date, VarcharLiteral hourSecond) { return applyInterval(date, hourSecond, TimeUnit.HOUR_SECOND, false); @@ -611,6 +739,11 @@ public static Expression hourSecondSub(TimestampTzLiteral date, VarcharLiteral h return applyInterval(date, hourSecond, TimeUnit.HOUR_SECOND, false); } + @ExecFunction(name = "hour_second_sub") + public static Expression hourSecondSub(TimeStampNsLiteral date, VarcharLiteral hourSecond) { + return applyInterval(date, hourSecond, TimeUnit.HOUR_SECOND, false); + } + @ExecFunction(name = "hour_microsecond_add") public static Expression hourMicrosecondAdd(DateTimeV2Literal date, VarcharLiteral hourMicrosecond) { return applyInterval(date, hourMicrosecond, TimeUnit.HOUR_MICROSECOND, true); @@ -621,6 +754,11 @@ public static Expression hourMicrosecondAdd(TimestampTzLiteral date, VarcharLite return applyInterval(date, hourMicrosecond, TimeUnit.HOUR_MICROSECOND, true); } + @ExecFunction(name = "hour_microsecond_add") + public static Expression hourMicrosecondAdd(TimeStampNsLiteral date, VarcharLiteral hourMicrosecond) { + return applyInterval(date, hourMicrosecond, TimeUnit.HOUR_MICROSECOND, true); + } + @ExecFunction(name = "hour_microsecond_sub") public static Expression hourMicrosecondSub(DateTimeV2Literal date, VarcharLiteral hourMicrosecond) { return applyInterval(date, hourMicrosecond, TimeUnit.HOUR_MICROSECOND, false); @@ -631,6 +769,11 @@ public static Expression hourMicrosecondSub(TimestampTzLiteral date, VarcharLite return applyInterval(date, hourMicrosecond, TimeUnit.HOUR_MICROSECOND, false); } + @ExecFunction(name = "hour_microsecond_sub") + public static Expression hourMicrosecondSub(TimeStampNsLiteral date, VarcharLiteral hourMicrosecond) { + return applyInterval(date, hourMicrosecond, TimeUnit.HOUR_MICROSECOND, false); + } + @ExecFunction(name = "minute_microsecond_add") public static Expression minuteMicrosecondAdd(DateTimeV2Literal date, VarcharLiteral minuteMicrosecond) { return applyInterval(date, minuteMicrosecond, TimeUnit.MINUTE_MICROSECOND, true); @@ -641,6 +784,11 @@ public static Expression minuteMicrosecondAdd(TimestampTzLiteral date, VarcharLi return applyInterval(date, minuteMicrosecond, TimeUnit.MINUTE_MICROSECOND, true); } + @ExecFunction(name = "minute_microsecond_add") + public static Expression minuteMicrosecondAdd(TimeStampNsLiteral date, VarcharLiteral minuteMicrosecond) { + return applyInterval(date, minuteMicrosecond, TimeUnit.MINUTE_MICROSECOND, true); + } + @ExecFunction(name = "minute_microsecond_sub") public static Expression minuteMicrosecondSub(DateTimeV2Literal date, VarcharLiteral minuteMicrosecond) { return applyInterval(date, minuteMicrosecond, TimeUnit.MINUTE_MICROSECOND, false); @@ -651,6 +799,11 @@ public static Expression minuteMicrosecondSub(TimestampTzLiteral date, VarcharLi return applyInterval(date, minuteMicrosecond, TimeUnit.MINUTE_MICROSECOND, false); } + @ExecFunction(name = "minute_microsecond_sub") + public static Expression minuteMicrosecondSub(TimeStampNsLiteral date, VarcharLiteral minuteMicrosecond) { + return applyInterval(date, minuteMicrosecond, TimeUnit.MINUTE_MICROSECOND, false); + } + @ExecFunction(name = "year_month_add") public static Expression yearMonthAdd(DateTimeV2Literal date, VarcharLiteral yearMonth) { return applyInterval(date, yearMonth, TimeUnit.YEAR_MONTH, true); @@ -661,6 +814,11 @@ public static Expression yearMonthAdd(TimestampTzLiteral date, VarcharLiteral ye return applyInterval(date, yearMonth, TimeUnit.YEAR_MONTH, true); } + @ExecFunction(name = "year_month_add") + public static Expression yearMonthAdd(TimeStampNsLiteral date, VarcharLiteral yearMonth) { + return applyInterval(date, yearMonth, TimeUnit.YEAR_MONTH, true); + } + @ExecFunction(name = "year_month_sub") public static Expression yearMonthSub(DateTimeV2Literal date, VarcharLiteral yearMonth) { return applyInterval(date, yearMonth, TimeUnit.YEAR_MONTH, false); @@ -671,6 +829,11 @@ public static Expression yearMonthSub(TimestampTzLiteral date, VarcharLiteral ye return applyInterval(date, yearMonth, TimeUnit.YEAR_MONTH, false); } + @ExecFunction(name = "year_month_sub") + public static Expression yearMonthSub(TimeStampNsLiteral date, VarcharLiteral yearMonth) { + return applyInterval(date, yearMonth, TimeUnit.YEAR_MONTH, false); + } + /** * datetime arithmetic function hours-add. */ @@ -684,6 +847,11 @@ public static Expression hoursAdd(TimestampTzLiteral date, IntegerLiteral hour) return date.plusHours(hour.getValue()); } + @ExecFunction(name = "hours_add") + public static Expression hoursAdd(TimeStampNsLiteral date, IntegerLiteral hour) { + return date.plusHours(hour.getValue()); + } + /** * datetime arithmetic function minutes-add. */ @@ -697,6 +865,11 @@ public static Expression minutesAdd(TimestampTzLiteral date, BigIntLiteral minut return date.plusMinutes(minute.getValue()); } + @ExecFunction(name = "minutes_add") + public static Expression minutesAdd(TimeStampNsLiteral date, BigIntLiteral minute) { + return date.plusMinutes(minute.getValue()); + } + /** * datetime arithmetic function seconds-add. */ @@ -710,6 +883,11 @@ public static Expression secondsAdd(TimestampTzLiteral date, BigIntLiteral secon return date.plusSeconds(second.getValue()); } + @ExecFunction(name = "seconds_add") + public static Expression secondsAdd(TimeStampNsLiteral date, BigIntLiteral second) { + return date.plusSeconds(second.getValue()); + } + /** * datetime arithmetic function microseconds-add. */ @@ -723,6 +901,11 @@ public static Expression microSecondsAdd(TimestampTzLiteral date, BigIntLiteral return date.plusMicroSeconds(microSecond.getValue()); } + @ExecFunction(name = "microseconds_add") + public static Expression microSecondsAdd(TimeStampNsLiteral date, BigIntLiteral microSecond) { + return date.plusMicroSeconds(microSecond.getValue()); + } + /** * datetime arithmetic function years-sub. */ @@ -741,6 +924,11 @@ public static Expression yearsSub(TimestampTzLiteral date, IntegerLiteral year) return yearsAdd(date, new IntegerLiteral(-year.getValue())); } + @ExecFunction(name = "years_sub") + public static Expression yearsSub(TimeStampNsLiteral date, IntegerLiteral year) { + return yearsAdd(date, new IntegerLiteral(-year.getValue())); + } + /** * datetime arithmetic function quarters-sub. */ @@ -759,6 +947,11 @@ public static Expression quartersSub(TimestampTzLiteral date, IntegerLiteral qua return quartersAdd(date, new IntegerLiteral(-quarter.getValue())); } + @ExecFunction(name = "quarters_sub") + public static Expression quartersSub(TimeStampNsLiteral date, IntegerLiteral quarter) { + return quartersAdd(date, new IntegerLiteral(-quarter.getValue())); + } + /** * datetime arithmetic function months-sub */ @@ -777,6 +970,11 @@ public static Expression monthsSub(TimestampTzLiteral date, IntegerLiteral month return monthsAdd(date, new IntegerLiteral(-month.getValue())); } + @ExecFunction(name = "months_sub") + public static Expression monthsSub(TimeStampNsLiteral date, IntegerLiteral month) { + return monthsAdd(date, new IntegerLiteral(-month.getValue())); + } + /** * datetime arithmetic function weeks-sub. */ @@ -795,6 +993,11 @@ public static Expression weeksSub(TimestampTzLiteral date, IntegerLiteral weeks) return date.plusWeeks(-weeks.getValue()); } + @ExecFunction(name = "weeks_sub") + public static Expression weeksSub(TimeStampNsLiteral date, IntegerLiteral weeks) { + return date.plusWeeks(-weeks.getValue()); + } + /** * datetime arithmetic function hours-sub */ @@ -808,6 +1011,11 @@ public static Expression hoursSub(TimestampTzLiteral date, IntegerLiteral hour) return hoursAdd(date, new IntegerLiteral(-hour.getValue())); } + @ExecFunction(name = "hours_sub") + public static Expression hoursSub(TimeStampNsLiteral date, IntegerLiteral hour) { + return hoursAdd(date, new IntegerLiteral(-hour.getValue())); + } + /** * datetime arithmetic function minutes-sub */ @@ -821,6 +1029,11 @@ public static Expression minutesSub(TimestampTzLiteral date, BigIntLiteral minut return minutesAdd(date, new BigIntLiteral(-minute.getValue())); } + @ExecFunction(name = "minutes_sub") + public static Expression minutesSub(TimeStampNsLiteral date, BigIntLiteral minute) { + return minutesAdd(date, new BigIntLiteral(-minute.getValue())); + } + /** * datetime arithmetic function seconds-sub */ @@ -834,6 +1047,11 @@ public static Expression secondsSub(TimestampTzLiteral date, BigIntLiteral secon return secondsAdd(date, new BigIntLiteral(-second.getValue())); } + @ExecFunction(name = "seconds_sub") + public static Expression secondsSub(TimeStampNsLiteral date, BigIntLiteral second) { + return secondsAdd(date, new BigIntLiteral(-second.getValue())); + } + /** * datetime arithmetic function microseconds_sub. */ @@ -847,6 +1065,11 @@ public static Expression microSecondsSub(TimestampTzLiteral date, BigIntLiteral return date.plusMicroSeconds(-microSecond.getValue()); } + @ExecFunction(name = "microseconds_sub") + public static Expression microSecondsSub(TimeStampNsLiteral date, BigIntLiteral microSecond) { + return date.plusMicroSeconds(-microSecond.getValue()); + } + /** * datetime arithmetic function milliseconds_add. */ @@ -860,6 +1083,11 @@ public static Expression milliSecondsAdd(TimestampTzLiteral date, BigIntLiteral return date.plusMilliSeconds(milliSecond.getValue()); } + @ExecFunction(name = "milliseconds_add") + public static Expression milliSecondsAdd(TimeStampNsLiteral date, BigIntLiteral milliSecond) { + return date.plusMilliSeconds(milliSecond.getValue()); + } + /** * datetime arithmetic function milliseconds_sub. */ @@ -873,6 +1101,11 @@ public static Expression milliSecondsSub(TimestampTzLiteral date, BigIntLiteral return date.plusMilliSeconds(-milliSecond.getValue()); } + @ExecFunction(name = "milliseconds_sub") + public static Expression milliSecondsSub(TimeStampNsLiteral date, BigIntLiteral milliSecond) { + return date.plusMilliSeconds(-milliSecond.getValue()); + } + /** * datetime arithmetic function datediff */ @@ -896,6 +1129,11 @@ public static Expression dateDiff(DateTimeV2Literal date1, DateTimeV2Literal dat return new IntegerLiteral(dateDiffByDayNumber(date1, date2)); } + @ExecFunction(name = "datediff") + public static Expression dateDiff(TimeStampNsLiteral date1, TimeStampNsLiteral date2) { + return new IntegerLiteral(dateDiffByDayNumber(date1, date2)); + } + private static int dateDiffByDayNumber(DateLiteral date1, DateLiteral date2) { return (int) (DateTimeExtractAndTransform.calcDayNumber(date1.getYear(), date1.getMonth(), date1.getDay()) - DateTimeExtractAndTransform.calcDayNumber(date2.getYear(), date2.getMonth(), date2.getDay())); @@ -920,6 +1158,12 @@ public static Expression time(DateTimeV2Literal date) { (int) date.getMicroSecond(), (int) date.getScale(), false); } + @ExecFunction(name = "time") + public static Expression time(TimeStampNsLiteral date) { + return new TimeV2Literal((int) date.getHour(), (int) date.getMinute(), (int) date.getSecond(), + (int) date.getMicroSecond(), TimeV2Type.MAX_SCALE, false); + } + /** * datetime arithmetic function add_time. */ @@ -938,6 +1182,11 @@ public static Expression addTime(TimestampTzLiteral date, TimeV2Literal time) { return date.plusMicroSeconds((long) time.getValue()); } + @ExecFunction(name = "add_time") + public static Expression addTime(TimeStampNsLiteral date, TimeV2Literal time) { + return date.plusMicroSeconds((long) time.getValue()); + } + /** * datetime arithmetic function sub_time. */ @@ -955,4 +1204,9 @@ public static Expression subTime(TimeV2Literal t1, TimeV2Literal t2) { public static Expression subTime(TimestampTzLiteral date, TimeV2Literal time) { return date.plusMicroSeconds(-(long) time.getValue()); } + + @ExecFunction(name = "sub_time") + public static Expression subTime(TimeStampNsLiteral date, TimeV2Literal time) { + return date.plusMicroSeconds(-(long) time.getValue()); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeExtractAndTransform.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeExtractAndTransform.java index ca55370c0d780d..7b214f3370b107 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeExtractAndTransform.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeExtractAndTransform.java @@ -38,6 +38,7 @@ import org.apache.doris.nereids.trees.expressions.literal.SmallIntLiteral; import org.apache.doris.nereids.trees.expressions.literal.StringLikeLiteral; import org.apache.doris.nereids.trees.expressions.literal.StringLiteral; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.trees.expressions.literal.TimeV2Literal; import org.apache.doris.nereids.trees.expressions.literal.TimestampTzLiteral; import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral; @@ -54,6 +55,7 @@ import org.apache.commons.lang3.StringUtils; import java.math.BigDecimal; +import java.math.BigInteger; import java.math.RoundingMode; import java.time.DayOfWeek; import java.time.Duration; @@ -117,6 +119,11 @@ public static Expression dateV2(DateTimeV2Literal dateTime) { return new DateV2Literal(dateTime.getYear(), dateTime.getMonth(), dateTime.getDay()); } + @ExecFunction(name = "datev2") + public static Expression dateV2(TimeStampNsLiteral dateTime) { + return new DateV2Literal(dateTime.getYear(), dateTime.getMonth(), dateTime.getDay()); + } + /** * Executable datetime extract year */ @@ -130,6 +137,11 @@ public static Expression year(DateTimeV2Literal date) { return new SmallIntLiteral(((short) date.getYear())); } + @ExecFunction(name = "year") + public static Expression year(TimeStampNsLiteral date) { + return new SmallIntLiteral((short) date.getYear()); + } + /** * Executable datetime extract century @@ -144,6 +156,11 @@ public static Expression century(DateTimeV2Literal date) { return new SmallIntLiteral((short) ((date.getYear() - 1) / 100 + 1)); } + @ExecFunction(name = "century") + public static Expression century(TimeStampNsLiteral date) { + return new SmallIntLiteral((short) ((date.getYear() - 1) / 100 + 1)); + } + /** * Executable datetime extract quarter @@ -158,6 +175,11 @@ public static Expression quarter(DateTimeV2Literal date) { return new TinyIntLiteral((byte) ((date.getMonth() - 1) / 3 + 1)); } + @ExecFunction(name = "quarter") + public static Expression quarter(TimeStampNsLiteral date) { + return new TinyIntLiteral((byte) ((date.getMonth() - 1) / 3 + 1)); + } + /** * Executable datetime extract month */ @@ -171,6 +193,11 @@ public static Expression month(DateTimeV2Literal date) { return new TinyIntLiteral((byte) date.getMonth()); } + @ExecFunction(name = "month") + public static Expression month(TimeStampNsLiteral date) { + return new TinyIntLiteral((byte) date.getMonth()); + } + /** * Executable datetime extract day */ @@ -184,6 +211,11 @@ public static Expression day(DateTimeV2Literal date) { return new TinyIntLiteral((byte) date.getDay()); } + @ExecFunction(name = "day") + public static Expression day(TimeStampNsLiteral date) { + return new TinyIntLiteral((byte) date.getDay()); + } + /** * Executable datetime extract hour */ @@ -192,6 +224,11 @@ public static Expression hour(DateTimeV2Literal date) { return new TinyIntLiteral(((byte) date.getHour())); } + @ExecFunction(name = "hour") + public static Expression hour(TimeStampNsLiteral date) { + return new TinyIntLiteral((byte) date.getHour()); + } + /** * Executable datetime extract hour */ @@ -200,6 +237,11 @@ public static Expression minute(DateTimeV2Literal date) { return new TinyIntLiteral(((byte) date.getMinute())); } + @ExecFunction(name = "minute") + public static Expression minute(TimeStampNsLiteral date) { + return new TinyIntLiteral((byte) date.getMinute()); + } + /** * Executable datetime extract second */ @@ -208,6 +250,11 @@ public static Expression second(DateTimeV2Literal date) { return new TinyIntLiteral(((byte) date.getSecond())); } + @ExecFunction(name = "second") + public static Expression second(TimeStampNsLiteral date) { + return new TinyIntLiteral((byte) date.getSecond()); + } + /** * Executable time extract second */ @@ -224,6 +271,11 @@ public static Expression microsecond(DateTimeV2Literal date) { return new IntegerLiteral(((int) date.getMicroSecond())); } + @ExecFunction(name = "microsecond") + public static Expression microsecond(TimeStampNsLiteral date) { + return new IntegerLiteral((int) date.getMicroSecond()); + } + /** * Executable time extract microsecond */ @@ -245,6 +297,11 @@ public static Expression dayOfYear(DateTimeV2Literal date) { return new SmallIntLiteral((short) date.getDayOfYear()); } + @ExecFunction(name = "dayofyear") + public static Expression dayOfYear(TimeStampNsLiteral date) { + return new SmallIntLiteral((short) date.getDayOfYear()); + } + /** * Executable datetime extract dayofmonth */ @@ -258,6 +315,11 @@ public static Expression dayOfMonth(DateTimeV2Literal date) { return new TinyIntLiteral((byte) date.toJavaDateType().getDayOfMonth()); } + @ExecFunction(name = "dayofmonth") + public static Expression dayOfMonth(TimeStampNsLiteral date) { + return new TinyIntLiteral((byte) date.toJavaDateType().getDayOfMonth()); + } + /** * Executable datetime extract dayofweek */ @@ -271,6 +333,11 @@ public static Expression dayOfWeek(DateTimeV2Literal date) { return new TinyIntLiteral((byte) (date.getDayOfWeek() % 7 + 1)); } + @ExecFunction(name = "dayofweek") + public static Expression dayOfWeek(TimeStampNsLiteral date) { + return new TinyIntLiteral((byte) (date.getDayOfWeek() % 7 + 1)); + } + private static int distanceToFirstDayOfWeek(LocalDateTime dateTime) { return dateTime.getDayOfWeek().getValue() - 1; } @@ -292,6 +359,17 @@ public static Expression dateFormat(DateTimeV2Literal date, StringLikeLiteral fo return new VarcharLiteral(DateTimeFormatterUtils.toFormatStringConservative(date, format, false)); } + /** TIMESTAMP_NS overload of date_format. */ + @ExecFunction(name = "date_format") + public static Expression dateFormat(TimeStampNsLiteral date, StringLikeLiteral format) { + if (StringUtils.trim(format.getValue()).length() > 128) { + throw new AnalysisException("The length of format string in date_format() function should not be greater" + + " than 128."); + } + format = (StringLikeLiteral) SupportJavaDateFormatter.translateJavaFormatter(format); + return new VarcharLiteral(DateTimeFormatterUtils.toFormatStringConservative(date, format, false)); + } + /** * time_format constant folding for time literal. */ @@ -316,6 +394,15 @@ public static Expression timeFormat(DateTimeV2Literal dateTime, StringLikeLitera return new VarcharLiteral(DateTimeFormatterUtils.toFormatStringConservative(dateTime, format, true)); } + @ExecFunction(name = "time_format") + public static Expression timeFormat(TimeStampNsLiteral dateTime, StringLikeLiteral format) { + if (StringUtils.trim(format.getValue()).length() > 128) { + throw new AnalysisException("The length of format string in time_format() function should not be greater" + + " than 128."); + } + return new VarcharLiteral(DateTimeFormatterUtils.toFormatStringConservative(dateTime, format, true)); + } + private static String padTwo(int value) { return value < 10 ? "0" + value : Integer.toString(value); } @@ -332,12 +419,24 @@ public static Expression yearMonth(DateTimeV2Literal dateTime) { return new VarcharLiteral(t.getYear() + "-" + padTwo(t.getMonthValue())); } + @ExecFunction(name = "year_month") + public static Expression yearMonth(TimeStampNsLiteral dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(t.getYear() + "-" + padTwo(t.getMonthValue())); + } + @ExecFunction(name = "day_hour") public static Expression dayHour(DateTimeV2Literal dateTime) { LocalDateTime t = dateTime.toJavaDateType(); return new VarcharLiteral(padTwo(t.getDayOfMonth()) + " " + padTwo(t.getHour())); } + @ExecFunction(name = "day_hour") + public static Expression dayHour(TimeStampNsLiteral dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getDayOfMonth()) + " " + padTwo(t.getHour())); + } + @ExecFunction(name = "day_minute") public static Expression dayMinute(DateTimeV2Literal dateTime) { LocalDateTime t = dateTime.toJavaDateType(); @@ -345,6 +444,13 @@ public static Expression dayMinute(DateTimeV2Literal dateTime) { + padTwo(t.getMinute())); } + @ExecFunction(name = "day_minute") + public static Expression dayMinute(TimeStampNsLiteral dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getDayOfMonth()) + " " + padTwo(t.getHour()) + ":" + + padTwo(t.getMinute())); + } + @ExecFunction(name = "day_second") public static Expression daySecond(DateTimeV2Literal dateTime) { LocalDateTime t = dateTime.toJavaDateType(); @@ -352,6 +458,13 @@ public static Expression daySecond(DateTimeV2Literal dateTime) { + padTwo(t.getMinute()) + ":" + padTwo(t.getSecond())); } + @ExecFunction(name = "day_second") + public static Expression daySecond(TimeStampNsLiteral dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getDayOfMonth()) + " " + padTwo(t.getHour()) + ":" + + padTwo(t.getMinute()) + ":" + padTwo(t.getSecond())); + } + @ExecFunction(name = "day_microsecond") public static Expression dayMicrosecond(DateTimeV2Literal dateTime) { LocalDateTime t = dateTime.toJavaDateType(); @@ -360,12 +473,26 @@ public static Expression dayMicrosecond(DateTimeV2Literal dateTime) { + padMicro(t.getNano() / 1000)); } + @ExecFunction(name = "day_microsecond") + public static Expression dayMicrosecond(TimeStampNsLiteral dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getDayOfMonth()) + " " + padTwo(t.getHour()) + ":" + + padTwo(t.getMinute()) + ":" + padTwo(t.getSecond()) + "." + + padMicro(t.getNano() / 1000)); + } + @ExecFunction(name = "hour_minute") public static Expression hourMinute(DateTimeV2Literal dateTime) { LocalDateTime t = dateTime.toJavaDateType(); return new VarcharLiteral(padTwo(t.getHour()) + ":" + padTwo(t.getMinute())); } + @ExecFunction(name = "hour_minute") + public static Expression hourMinute(TimeStampNsLiteral dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getHour()) + ":" + padTwo(t.getMinute())); + } + @ExecFunction(name = "hour_second") public static Expression hourSecond(DateTimeV2Literal dateTime) { LocalDateTime t = dateTime.toJavaDateType(); @@ -373,6 +500,13 @@ public static Expression hourSecond(DateTimeV2Literal dateTime) { + padTwo(t.getSecond())); } + @ExecFunction(name = "hour_second") + public static Expression hourSecond(TimeStampNsLiteral dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getHour()) + ":" + padTwo(t.getMinute()) + ":" + + padTwo(t.getSecond())); + } + @ExecFunction(name = "hour_microsecond") public static Expression hourMicrosecond(DateTimeV2Literal dateTime) { LocalDateTime t = dateTime.toJavaDateType(); @@ -380,12 +514,25 @@ public static Expression hourMicrosecond(DateTimeV2Literal dateTime) { + padTwo(t.getSecond()) + "." + padMicro(t.getNano() / 1000)); } + @ExecFunction(name = "hour_microsecond") + public static Expression hourMicrosecond(TimeStampNsLiteral dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getHour()) + ":" + padTwo(t.getMinute()) + ":" + + padTwo(t.getSecond()) + "." + padMicro(t.getNano() / 1000)); + } + @ExecFunction(name = "minute_second") public static Expression minuteSecond(DateTimeV2Literal dateTime) { LocalDateTime t = dateTime.toJavaDateType(); return new VarcharLiteral(padTwo(t.getMinute()) + ":" + padTwo(t.getSecond())); } + @ExecFunction(name = "minute_second") + public static Expression minuteSecond(TimeStampNsLiteral dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getMinute()) + ":" + padTwo(t.getSecond())); + } + @ExecFunction(name = "minute_microsecond") public static Expression minuteMicrosecond(DateTimeV2Literal dateTime) { LocalDateTime t = dateTime.toJavaDateType(); @@ -393,12 +540,25 @@ public static Expression minuteMicrosecond(DateTimeV2Literal dateTime) { + padMicro(t.getNano() / 1000)); } + @ExecFunction(name = "minute_microsecond") + public static Expression minuteMicrosecond(TimeStampNsLiteral dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getMinute()) + ":" + padTwo(t.getSecond()) + "." + + padMicro(t.getNano() / 1000)); + } + @ExecFunction(name = "second_microsecond") public static Expression secondMicrosecond(DateTimeV2Literal dateTime) { LocalDateTime t = dateTime.toJavaDateType(); return new VarcharLiteral(padTwo(t.getSecond()) + "." + padMicro(t.getNano() / 1000)); } + @ExecFunction(name = "second_microsecond") + public static Expression secondMicrosecond(TimeStampNsLiteral dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getSecond()) + "." + padMicro(t.getNano() / 1000)); + } + /** * datetime arithmetic function date */ @@ -407,6 +567,11 @@ public static Expression date(DateTimeV2Literal dateTime) throws AnalysisExcepti return new DateV2Literal(dateTime.getYear(), dateTime.getMonth(), dateTime.getDay()); } + @ExecFunction(name = "date") + public static Expression date(TimeStampNsLiteral dateTime) throws AnalysisException { + return new DateV2Literal(dateTime.getYear(), dateTime.getMonth(), dateTime.getDay()); + } + /** * datetime arithmetic function date-trunc */ @@ -416,6 +581,12 @@ public static Expression dateTrunc(DateTimeV2Literal date, StringLikeLiteral tru dateTruncHelper(date.toJavaDateType(), trunc.getValue()), date.getScale()); } + @ExecFunction(name = "date_trunc") + public static Expression dateTrunc(TimeStampNsLiteral date, StringLikeLiteral trunc) { + return TimeStampNsLiteral.fromJavaDateType( + dateTruncHelper(date.toJavaDateType(), trunc.getValue())); + } + @ExecFunction(name = "date_trunc") public static Expression dateTrunc(DateV2Literal date, StringLikeLiteral trunc) { return DateV2Literal.fromJavaDateType(dateTruncHelper(date.toJavaDateType(), trunc.getValue())); @@ -427,6 +598,12 @@ public static Expression dateTrunc(StringLikeLiteral trunc, DateTimeV2Literal da dateTruncHelper(date.toJavaDateType(), trunc.getValue()), date.getScale()); } + @ExecFunction(name = "date_trunc") + public static Expression dateTrunc(StringLikeLiteral trunc, TimeStampNsLiteral date) { + return TimeStampNsLiteral.fromJavaDateType( + dateTruncHelper(date.toJavaDateType(), trunc.getValue())); + } + @ExecFunction(name = "date_trunc") public static Expression dateTrunc(StringLikeLiteral trunc, DateV2Literal date) { return DateV2Literal.fromJavaDateType(dateTruncHelper(date.toJavaDateType(), trunc.getValue())); @@ -499,6 +676,13 @@ public static Expression lastDay(DateTimeV2Literal date) { return DateV2Literal.fromJavaDateType(nextMonthFirstDay.minusDays(1)); } + @ExecFunction(name = "last_day") + public static Expression lastDay(TimeStampNsLiteral date) { + LocalDateTime nextMonthFirstDay = LocalDateTime.of((int) date.getYear(), (int) date.getMonth(), 1, + 0, 0, 0).plusMonths(1); + return DateV2Literal.fromJavaDateType(nextMonthFirstDay.minusDays(1)); + } + /** * datetime transformation function: to_monday */ @@ -512,6 +696,11 @@ public static Expression toMonday(DateTimeV2Literal date) { return DateV2Literal.fromJavaDateType(toMonday(date.toJavaDateType())); } + @ExecFunction(name = "to_monday") + public static Expression toMonday(TimeStampNsLiteral date) { + return DateV2Literal.fromJavaDateType(toMonday(date.toJavaDateType())); + } + private static LocalDateTime toMonday(LocalDateTime dateTime) { LocalDateTime specialUpperBound = LocalDateTime.of(1970, 1, 4, 23, 59, 59, 999_999_999); LocalDateTime specialLowerBound = LocalDateTime.of(1970, 1, 1, 0, 0, 0); @@ -618,6 +807,12 @@ public static Expression unixTimestamp(DateTimeV2Literal date) { new BigDecimal(getTimestamp(date.toJavaDateType()))); } + @ExecFunction(name = "unix_timestamp") + public static Expression unixTimestamp(TimeStampNsLiteral date) { + return new DecimalV3Literal(DecimalV3Type.createDecimalV3TypeLooseCheck(21, 9), + new BigDecimal(getTimestamp(date.toJavaDateType(), 9))); + } + /** * date transformation function: unix_timestamp */ @@ -637,6 +832,10 @@ public static Expression unixTimestamp(StringLikeLiteral date, StringLikeLiteral } private static String getTimestamp(LocalDateTime dateTime) { + return getTimestamp(dateTime, 6); + } + + private static String getTimestamp(LocalDateTime dateTime, int scale) { LocalDateTime specialLowerBound = LocalDateTime.of(1970, 1, 1, 0, 0, 0); dateTime = dateTime.atZone(DateUtils.getTimeZone()) .toOffsetDateTime().atZoneSameInstant(ZoneId.of("UTC+0")) @@ -651,7 +850,8 @@ private static String getTimestamp(LocalDateTime dateTime) { if (duration.getNano() == 0) { return String.valueOf(duration.getSeconds()); } else { - return duration.getSeconds() + "." + String.format("%06d", duration.getNano() / 1000); + String nanos = String.format("%09d", duration.getNano()); + return duration.getSeconds() + "." + nanos.substring(0, scale); } } @@ -663,6 +863,11 @@ public static Expression toDate(DateTimeV2Literal date) { return new DateV2Literal(date.getYear(), date.getMonth(), date.getDay()); } + @ExecFunction(name = "to_date") + public static Expression toDate(TimeStampNsLiteral date) { + return new DateV2Literal(date.getYear(), date.getMonth(), date.getDay()); + } + /** * date transformation function: to_days */ @@ -676,6 +881,11 @@ public static Expression toDays(DateTimeV2Literal date) { return new IntegerLiteral((int) calcDayNumber(date.getYear(), date.getMonth(), date.getDay())); } + @ExecFunction(name = "to_days") + public static Expression toDays(TimeStampNsLiteral date) { + return new IntegerLiteral((int) calcDayNumber(date.getYear(), date.getMonth(), date.getDay())); + } + /** * date transformation function: to_seconds */ @@ -690,6 +900,12 @@ public static Expression toSeconds(DateTimeV2Literal date) { + date.getHour() * 3600L + date.getMinute() * 60L + date.getSecond()); } + @ExecFunction(name = "to_seconds") + public static Expression toSeconds(TimeStampNsLiteral date) { + return new BigIntLiteral(calcDayNumber(date.getYear(), date.getMonth(), date.getDay()) * 86400L + + date.getHour() * 3600L + date.getMinute() * 60L + date.getSecond()); + } + // Java Duration cannot represent days before 0000-01-01, so using it would turn // TO_DAYS('0000-01-01') into the diff between that date and itself (0). // We use BE's arithmetic instead so 0000-01-01 returns 1 as expected. @@ -807,11 +1023,29 @@ public static Expression timestamp(DateTimeV2Literal datetime) { return datetime; } + @ExecFunction(name = "timestamp") + public static Expression timestamp(TimeStampNsLiteral datetime) { + return datetime; + } + /** * date transformation function: convert_tz */ @ExecFunction(name = "convert_tz") public static Expression convertTz(DateTimeV2Literal datetime, StringLikeLiteral fromTz, StringLikeLiteral toTz) { + return DateTimeV2Literal.fromJavaDateType( + convertTz(datetime.toJavaDateType(), fromTz, toTz), datetime.getDataType().getScale()); + } + + @ExecFunction(name = "convert_tz") + public static Expression convertTz(TimeStampNsLiteral datetime, StringLikeLiteral fromTz, + StringLikeLiteral toTz) { + return TimeStampNsLiteral.fromJavaDateType( + convertTz(datetime.toJavaDateType(), fromTz, toTz)); + } + + private static LocalDateTime convertTz(LocalDateTime datetime, StringLikeLiteral fromTz, + StringLikeLiteral toTz) { // Validate timezone offset ranges before parsing validateTimezoneOffset(fromTz.getStringValue()); validateTimezoneOffset(toTz.getStringValue()); @@ -824,10 +1058,8 @@ public static Expression convertTz(DateTimeV2Literal datetime, StringLikeLiteral ZoneId fromZone = ZoneId.from(zoneFormatter.parse(fromTz.getStringValue())); ZoneId toZone = ZoneId.from(zoneFormatter.parse(toTz.getStringValue())); - LocalDateTime localDateTime = datetime.toJavaDateType(); - Instant instant = DateTimeLiteral.convertLocalToInstant(localDateTime, fromZone); - return DateTimeV2Literal.fromJavaDateType(LocalDateTime.ofInstant(instant, toZone), - datetime.getDataType().getScale()); + Instant instant = DateTimeLiteral.convertLocalToInstant(datetime, fromZone); + return LocalDateTime.ofInstant(instant, toZone); } private static void validateTimezoneOffset(String timezone) { @@ -862,6 +1094,11 @@ public static Expression weekDay(DateTimeV2Literal date) { return new TinyIntLiteral((byte) ((date.toJavaDateType().getDayOfWeek().getValue() + 6) % 7)); } + @ExecFunction(name = "weekday") + public static Expression weekDay(TimeStampNsLiteral date) { + return new TinyIntLiteral((byte) ((date.toJavaDateType().getDayOfWeek().getValue() + 6) % 7)); + } + @ExecFunction(name = "week") public static Expression week(DateTimeV2Literal dateTime) { return week(dateTime.toJavaDateType(), 0); @@ -872,6 +1109,16 @@ public static Expression week(DateTimeV2Literal dateTime, IntegerLiteral mode) { return week(dateTime.toJavaDateType(), mode.getIntValue()); } + @ExecFunction(name = "week") + public static Expression week(TimeStampNsLiteral dateTime) { + return week(dateTime.toJavaDateType(), 0); + } + + @ExecFunction(name = "week") + public static Expression week(TimeStampNsLiteral dateTime, IntegerLiteral mode) { + return week(dateTime.toJavaDateType(), mode.getIntValue()); + } + @ExecFunction(name = "week") public static Expression week(DateV2Literal date) { return week(date.toJavaDateType(), 0); @@ -952,6 +1199,11 @@ public static Expression yearWeek(DateTimeV2Literal dateTime, IntegerLiteral mod return yearWeek(dateTime.toJavaDateType(), mode.getIntValue()); } + @ExecFunction(name = "yearweek") + public static Expression yearWeek(TimeStampNsLiteral dateTime, IntegerLiteral mode) { + return yearWeek(dateTime.toJavaDateType(), mode.getIntValue()); + } + @ExecFunction(name = "yearweek") public static Expression yearWeek(DateV2Literal date) { return yearWeek(date.toJavaDateType(), 0); @@ -962,6 +1214,11 @@ public static Expression yearWeek(DateTimeV2Literal dateTime) { return yearWeek(dateTime.toJavaDateType(), 0); } + @ExecFunction(name = "yearweek") + public static Expression yearWeek(TimeStampNsLiteral dateTime) { + return yearWeek(dateTime.toJavaDateType(), 0); + } + /** * the impl of function yearWeek(date/datetime, mode) */ @@ -1051,6 +1308,11 @@ public static Expression weekOfYear(DateV2Literal date) { return new TinyIntLiteral((byte) date.toJavaDateType().get(WeekFields.ISO.weekOfWeekBasedYear())); } + @ExecFunction(name = "weekofyear") + public static Expression weekOfYear(TimeStampNsLiteral date) { + return new TinyIntLiteral((byte) date.toJavaDateType().get(WeekFields.ISO.weekOfWeekBasedYear())); + } + /** * Get locale from session variable lc_time_names, fallback to default if not available */ @@ -1078,6 +1340,12 @@ public static Expression dayName(DateV2Literal date) { getSessionLocale())); } + @ExecFunction(name = "dayname") + public static Expression dayName(TimeStampNsLiteral date) { + return new VarcharLiteral(date.toJavaDateType().getDayOfWeek().getDisplayName(TextStyle.FULL, + getSessionLocale())); + } + @ExecFunction(name = "monthname") public static Expression monthName(DateTimeV2Literal dateTime) { return new VarcharLiteral(dateTime.toJavaDateType().getMonth().getDisplayName(TextStyle.FULL, @@ -1090,6 +1358,12 @@ public static Expression monthName(DateV2Literal date) { getSessionLocale())); } + @ExecFunction(name = "monthname") + public static Expression monthName(TimeStampNsLiteral date) { + return new VarcharLiteral(date.toJavaDateType().getMonth().getDisplayName(TextStyle.FULL, + getSessionLocale())); + } + @ExecFunction(name = "from_second") public static Expression fromSecond(BigIntLiteral second) { return fromMicroSecond(second.getValue() * 1000 * 1000, FromSecond.RESULT_SCALE); @@ -1117,6 +1391,14 @@ private static Expression fromMicroSecond(long microSecond, int scale) { dateTime.getMinute(), dateTime.getSecond(), dateTime.getNano() / 1000); } + private static long timestampNsDiff(TimeStampNsLiteral t1, TimeStampNsLiteral t2, + long nanosPerUnit) { + Duration duration = Duration.between(t2.toJavaDateType(), t1.toJavaDateType()); + BigInteger nanos = BigInteger.valueOf(duration.getSeconds()).multiply(BigInteger.valueOf(1_000_000_000L)) + .add(BigInteger.valueOf(duration.getNano())); + return nanos.divide(BigInteger.valueOf(nanosPerUnit)).longValueExact(); + } + @ExecFunction(name = "microseconds_diff") public static Expression microsecondsDiff(DateTimeV2Literal t1, DateTimeV2Literal t2) { return new BigIntLiteral(DateTimeV2Literal.datetimeDiffInMicroSeconds(t1, t2)); @@ -1127,6 +1409,11 @@ public static Expression microsecondsDiff(TimestampTzLiteral t1, TimestampTzLite return new BigIntLiteral(DateTimeV2Literal.datetimeDiffInMicroSeconds(t1, t2)); } + @ExecFunction(name = "microseconds_diff") + public static Expression microsecondsDiff(TimeStampNsLiteral t1, TimeStampNsLiteral t2) { + return new BigIntLiteral(timestampNsDiff(t1, t2, 1_000L)); + } + @ExecFunction(name = "milliseconds_diff") public static Expression millisecondsDiff(DateTimeV2Literal t1, DateTimeV2Literal t2) { return new BigIntLiteral(DateTimeV2Literal.datetimeDiffInMicroSeconds(t1, t2) / 1000L); @@ -1137,6 +1424,11 @@ public static Expression millisecondsDiff(TimestampTzLiteral t1, TimestampTzLite return new BigIntLiteral(DateTimeV2Literal.datetimeDiffInMicroSeconds(t1, t2) / 1000L); } + @ExecFunction(name = "milliseconds_diff") + public static Expression millisecondsDiff(TimeStampNsLiteral t1, TimeStampNsLiteral t2) { + return new BigIntLiteral(timestampNsDiff(t1, t2, 1_000_000L)); + } + @ExecFunction(name = "seconds_diff") public static Expression secondsDiff(DateTimeV2Literal t1, DateTimeV2Literal t2) { return new BigIntLiteral(DateTimeV2Literal.datetimeDiffInSecondsRoundToZeroByMicroSecond(t1, t2)); @@ -1147,6 +1439,11 @@ public static Expression secondsDiff(TimestampTzLiteral t1, TimestampTzLiteral t return new BigIntLiteral(DateTimeV2Literal.datetimeDiffInSecondsRoundToZeroByMicroSecond(t1, t2)); } + @ExecFunction(name = "seconds_diff") + public static Expression secondsDiff(TimeStampNsLiteral t1, TimeStampNsLiteral t2) { + return new BigIntLiteral(timestampNsDiff(t1, t2, 1_000_000_000L)); + } + @ExecFunction(name = "seconds_diff") public static Expression secondsDiff(DateTimeV2Literal t1, DateV2Literal t2) { return new BigIntLiteral(DateTimeV2Literal.datetimeDiffInSecondsRoundToZeroByMicroSecond(t1, t2)); @@ -1172,6 +1469,11 @@ public static Expression minutesDiff(TimestampTzLiteral t1, TimestampTzLiteral t return new BigIntLiteral(DateTimeV2Literal.datetimeDiffInSecondsRoundToZeroByMicroSecond(t1, t2) / 60L); } + @ExecFunction(name = "minutes_diff") + public static Expression minutesDiff(TimeStampNsLiteral t1, TimeStampNsLiteral t2) { + return new BigIntLiteral(timestampNsDiff(t1, t2, 60_000_000_000L)); + } + @ExecFunction(name = "minutes_diff") public static Expression minutesDiff(DateTimeV2Literal t1, DateV2Literal t2) { return new BigIntLiteral(DateTimeV2Literal.datetimeDiffInSecondsRoundToZeroByMicroSecond(t1, t2) / 60L); @@ -1197,6 +1499,11 @@ public static Expression hoursDiff(TimestampTzLiteral t1, TimestampTzLiteral t2) return new BigIntLiteral(DateTimeV2Literal.datetimeDiffInSecondsRoundToZeroByMicroSecond(t1, t2) / 60L / 60L); } + @ExecFunction(name = "hours_diff") + public static Expression hoursDiff(TimeStampNsLiteral t1, TimeStampNsLiteral t2) { + return new BigIntLiteral(timestampNsDiff(t1, t2, 3_600_000_000_000L)); + } + @ExecFunction(name = "hours_diff") public static Expression hoursDiff(DateTimeV2Literal t1, DateV2Literal t2) { return new BigIntLiteral(DateTimeV2Literal.datetimeDiffInSecondsRoundToZeroByMicroSecond(t1, t2) / 60L / 60L); @@ -1222,6 +1529,11 @@ public static Expression daysDiff(TimestampTzLiteral t1, TimestampTzLiteral t2) return daysDiff((DateLiteral) t1, t2); } + @ExecFunction(name = "days_diff") + public static Expression daysDiff(TimeStampNsLiteral t1, TimeStampNsLiteral t2) { + return daysDiff((DateLiteral) t1, t2); + } + @ExecFunction(name = "days_diff") public static Expression daysDiff(DateTimeV2Literal t1, DateV2Literal t2) { return daysDiff((DateLiteral) t1, t2); @@ -1251,6 +1563,11 @@ public static Expression weeksDiff(TimestampTzLiteral t1, TimestampTzLiteral t2) return weeksDiff((DateLiteral) t1, t2); } + @ExecFunction(name = "weeks_diff") + public static Expression weeksDiff(TimeStampNsLiteral t1, TimeStampNsLiteral t2) { + return weeksDiff((DateLiteral) t1, t2); + } + @ExecFunction(name = "weeks_diff") public static Expression weeksDiff(DateTimeV2Literal t1, DateV2Literal t2) { return weeksDiff((DateLiteral) t1, t2); @@ -1280,6 +1597,11 @@ public static Expression monthsDiff(TimestampTzLiteral t1, TimestampTzLiteral t2 return new BigIntLiteral(ChronoUnit.MONTHS.between(t2.toJavaDateType(), t1.toJavaDateType())); } + @ExecFunction(name = "months_diff") + public static Expression monthsDiff(TimeStampNsLiteral t1, TimeStampNsLiteral t2) { + return new BigIntLiteral(ChronoUnit.MONTHS.between(t2.toJavaDateType(), t1.toJavaDateType())); + } + @ExecFunction(name = "months_diff") public static Expression monthsDiff(DateTimeV2Literal t1, DateV2Literal t2) { return new BigIntLiteral(ChronoUnit.MONTHS.between(t2.toJavaDateType(), t1.toJavaDateType())); @@ -1305,6 +1627,11 @@ public static Expression quartersDiff(TimestampTzLiteral t1, TimestampTzLiteral return new BigIntLiteral(ChronoUnit.MONTHS.between(t2.toJavaDateType(), t1.toJavaDateType()) / 3); } + @ExecFunction(name = "quarters_diff") + public static Expression quartersDiff(TimeStampNsLiteral t1, TimeStampNsLiteral t2) { + return new BigIntLiteral(ChronoUnit.MONTHS.between(t2.toJavaDateType(), t1.toJavaDateType()) / 3); + } + @ExecFunction(name = "quarters_diff") public static Expression quartersDiff(DateV2Literal t1, DateV2Literal t2) { return new BigIntLiteral(ChronoUnit.MONTHS.between(t2.toJavaDateType(), t1.toJavaDateType()) / 3); @@ -1320,6 +1647,11 @@ public static Expression yearsDiff(TimestampTzLiteral t1, TimestampTzLiteral t2) return new BigIntLiteral(ChronoUnit.YEARS.between(t2.toJavaDateType(), t1.toJavaDateType())); } + @ExecFunction(name = "years_diff") + public static Expression yearsDiff(TimeStampNsLiteral t1, TimeStampNsLiteral t2) { + return new BigIntLiteral(ChronoUnit.YEARS.between(t2.toJavaDateType(), t1.toJavaDateType())); + } + @ExecFunction(name = "years_diff") public static Expression yearsDiff(DateTimeV2Literal t1, DateV2Literal t2) { return new BigIntLiteral(ChronoUnit.YEARS.between(t2.toJavaDateType(), t1.toJavaDateType())); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/StringArithmetic.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/StringArithmetic.java index 6347bec6dc096e..7e8d03ffe76a2e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/StringArithmetic.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/StringArithmetic.java @@ -38,6 +38,7 @@ import org.apache.doris.nereids.trees.expressions.literal.SmallIntLiteral; import org.apache.doris.nereids.trees.expressions.literal.StringLikeLiteral; import org.apache.doris.nereids.trees.expressions.literal.StringLiteral; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral; import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral; import org.apache.doris.nereids.types.ArrayType; @@ -669,6 +670,11 @@ public static Expression fieldDateTimeV2(DateTimeV2Literal first, DateTimeV2Lite return new IntegerLiteral(compareLiteral(first, second)); } + @ExecFunction(name = "field") + public static Expression fieldTimeStampNs(TimeStampNsLiteral first, TimeStampNsLiteral... second) { + return new IntegerLiteral(compareLiteral(first, second)); + } + /** * Executable arithmetic functions field */ diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/TimeRoundSeries.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/TimeRoundSeries.java index c32f733bedbae5..e27fb2bf2b6163 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/TimeRoundSeries.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/TimeRoundSeries.java @@ -25,6 +25,7 @@ import org.apache.doris.nereids.trees.expressions.literal.DateTimeV2Literal; import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal; import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.trees.expressions.literal.TimestampTzLiteral; import org.apache.doris.qe.ConnectContext; @@ -104,14 +105,14 @@ private static LocalDateTime getDateCeilOrFloor(DATE tag, LocalDateTime date, in + (dt.getHour() - start.getHour()) * 60 * 60 + (dt.getMinute() - start.getMinute()) * 60 + (dt.getSecond() - start.getSecond()); - trivialPart = dt.getMicroSecond() - start.getMicroSecond(); + trivialPart = date.getNano() - origin.getNano(); break; } default: { return null; } } - trivialPart = (trivialPart == 0 ? dt.getMicroSecond() - start.getMicroSecond() : trivialPart); + trivialPart = (trivialPart == 0 ? date.getNano() - origin.getNano() : trivialPart); if (getCeil) { diff = diff + (trivialPart > 0 ? 1 : 0); } else { @@ -1268,4 +1269,318 @@ public static Expression secondFloor(TimestampTzLiteral date, IntegerLiteral per return TimestampTzLiteral.fromJavaDateType(getDateCeilOrFloorForTimestampTz(DATE.SECOND, date.toJavaDateType(), period.getValue(), origin.toJavaDateType(), false), date.commonScale(origin)); } + + private static Expression roundTimeStampNs(DATE tag, TimeStampNsLiteral date, int period, + LocalDateTime origin, boolean getCeil) { + LocalDateTime result = getDateCeilOrFloor(tag, date.toJavaDateType(), period, origin, getCeil); + return TimeStampNsLiteral.fromJavaDateType(result.withNano(origin.getNano())); + } + + /** TIMESTAMP_NS overloads of year_ceil. */ + @ExecFunction(name = "year_ceil") + public static Expression yearCeilTimeStampNs(TimeStampNsLiteral date) { + return roundTimeStampNs(DATE.YEAR, date, 1, START_ORIGINAL_DAY, true); + } + + @ExecFunction(name = "year_ceil") + public static Expression yearCeilTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period) { + return roundTimeStampNs(DATE.YEAR, date, period.getValue(), START_ORIGINAL_DAY, true); + } + + @ExecFunction(name = "year_ceil") + public static Expression yearCeilTimeStampNs(TimeStampNsLiteral date, TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.YEAR, date, 1, origin.toJavaDateType(), true); + } + + @ExecFunction(name = "year_ceil") + public static Expression yearCeilTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period, + TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.YEAR, date, period.getValue(), origin.toJavaDateType(), true); + } + + /** TIMESTAMP_NS overloads of quarter_ceil. */ + @ExecFunction(name = "quarter_ceil") + public static Expression quarterCeilTimeStampNs(TimeStampNsLiteral date) { + return roundTimeStampNs(DATE.QUARTER, date, 1, START_ORIGINAL_DAY, true); + } + + @ExecFunction(name = "quarter_ceil") + public static Expression quarterCeilTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period) { + return roundTimeStampNs(DATE.QUARTER, date, period.getValue(), START_ORIGINAL_DAY, true); + } + + @ExecFunction(name = "quarter_ceil") + public static Expression quarterCeilTimeStampNs(TimeStampNsLiteral date, TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.QUARTER, date, 1, origin.toJavaDateType(), true); + } + + @ExecFunction(name = "quarter_ceil") + public static Expression quarterCeilTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period, + TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.QUARTER, date, period.getValue(), origin.toJavaDateType(), true); + } + + /** TIMESTAMP_NS overloads of month_ceil. */ + @ExecFunction(name = "month_ceil") + public static Expression monthCeilTimeStampNs(TimeStampNsLiteral date) { + return roundTimeStampNs(DATE.MONTH, date, 1, START_ORIGINAL_DAY, true); + } + + @ExecFunction(name = "month_ceil") + public static Expression monthCeilTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period) { + return roundTimeStampNs(DATE.MONTH, date, period.getValue(), START_ORIGINAL_DAY, true); + } + + @ExecFunction(name = "month_ceil") + public static Expression monthCeilTimeStampNs(TimeStampNsLiteral date, TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.MONTH, date, 1, origin.toJavaDateType(), true); + } + + @ExecFunction(name = "month_ceil") + public static Expression monthCeilTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period, + TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.MONTH, date, period.getValue(), origin.toJavaDateType(), true); + } + + /** TIMESTAMP_NS overloads of day_ceil. */ + @ExecFunction(name = "day_ceil") + public static Expression dayCeilTimeStampNs(TimeStampNsLiteral date) { + return roundTimeStampNs(DATE.DAY, date, 1, START_ORIGINAL_DAY, true); + } + + @ExecFunction(name = "day_ceil") + public static Expression dayCeilTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period) { + return roundTimeStampNs(DATE.DAY, date, period.getValue(), START_ORIGINAL_DAY, true); + } + + @ExecFunction(name = "day_ceil") + public static Expression dayCeilTimeStampNs(TimeStampNsLiteral date, TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.DAY, date, 1, origin.toJavaDateType(), true); + } + + @ExecFunction(name = "day_ceil") + public static Expression dayCeilTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period, + TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.DAY, date, period.getValue(), origin.toJavaDateType(), true); + } + + /** TIMESTAMP_NS overloads of hour_ceil. */ + @ExecFunction(name = "hour_ceil") + public static Expression hourCeilTimeStampNs(TimeStampNsLiteral date) { + return roundTimeStampNs(DATE.HOUR, date, 1, START_ORIGINAL_DAY, true); + } + + @ExecFunction(name = "hour_ceil") + public static Expression hourCeilTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period) { + return roundTimeStampNs(DATE.HOUR, date, period.getValue(), START_ORIGINAL_DAY, true); + } + + @ExecFunction(name = "hour_ceil") + public static Expression hourCeilTimeStampNs(TimeStampNsLiteral date, TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.HOUR, date, 1, origin.toJavaDateType(), true); + } + + @ExecFunction(name = "hour_ceil") + public static Expression hourCeilTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period, + TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.HOUR, date, period.getValue(), origin.toJavaDateType(), true); + } + + /** TIMESTAMP_NS overloads of minute_ceil. */ + @ExecFunction(name = "minute_ceil") + public static Expression minuteCeilTimeStampNs(TimeStampNsLiteral date) { + return roundTimeStampNs(DATE.MINUTE, date, 1, START_ORIGINAL_DAY, true); + } + + @ExecFunction(name = "minute_ceil") + public static Expression minuteCeilTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period) { + return roundTimeStampNs(DATE.MINUTE, date, period.getValue(), START_ORIGINAL_DAY, true); + } + + @ExecFunction(name = "minute_ceil") + public static Expression minuteCeilTimeStampNs(TimeStampNsLiteral date, TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.MINUTE, date, 1, origin.toJavaDateType(), true); + } + + @ExecFunction(name = "minute_ceil") + public static Expression minuteCeilTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period, + TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.MINUTE, date, period.getValue(), origin.toJavaDateType(), true); + } + + /** TIMESTAMP_NS overloads of second_ceil. */ + @ExecFunction(name = "second_ceil") + public static Expression secondCeilTimeStampNs(TimeStampNsLiteral date) { + return roundTimeStampNs(DATE.SECOND, date, 1, START_ORIGINAL_DAY, true); + } + + @ExecFunction(name = "second_ceil") + public static Expression secondCeilTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period) { + return roundTimeStampNs(DATE.SECOND, date, period.getValue(), START_ORIGINAL_DAY, true); + } + + @ExecFunction(name = "second_ceil") + public static Expression secondCeilTimeStampNs(TimeStampNsLiteral date, TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.SECOND, date, 1, origin.toJavaDateType(), true); + } + + @ExecFunction(name = "second_ceil") + public static Expression secondCeilTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period, + TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.SECOND, date, period.getValue(), origin.toJavaDateType(), true); + } + + /** TIMESTAMP_NS overloads of year_floor. */ + @ExecFunction(name = "year_floor") + public static Expression yearFloorTimeStampNs(TimeStampNsLiteral date) { + return roundTimeStampNs(DATE.YEAR, date, 1, START_ORIGINAL_DAY, false); + } + + @ExecFunction(name = "year_floor") + public static Expression yearFloorTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period) { + return roundTimeStampNs(DATE.YEAR, date, period.getValue(), START_ORIGINAL_DAY, false); + } + + @ExecFunction(name = "year_floor") + public static Expression yearFloorTimeStampNs(TimeStampNsLiteral date, TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.YEAR, date, 1, origin.toJavaDateType(), false); + } + + @ExecFunction(name = "year_floor") + public static Expression yearFloorTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period, + TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.YEAR, date, period.getValue(), origin.toJavaDateType(), false); + } + + /** TIMESTAMP_NS overloads of quarter_floor. */ + @ExecFunction(name = "quarter_floor") + public static Expression quarterFloorTimeStampNs(TimeStampNsLiteral date) { + return roundTimeStampNs(DATE.QUARTER, date, 1, START_ORIGINAL_DAY, false); + } + + @ExecFunction(name = "quarter_floor") + public static Expression quarterFloorTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period) { + return roundTimeStampNs(DATE.QUARTER, date, period.getValue(), START_ORIGINAL_DAY, false); + } + + @ExecFunction(name = "quarter_floor") + public static Expression quarterFloorTimeStampNs(TimeStampNsLiteral date, TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.QUARTER, date, 1, origin.toJavaDateType(), false); + } + + @ExecFunction(name = "quarter_floor") + public static Expression quarterFloorTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period, + TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.QUARTER, date, period.getValue(), origin.toJavaDateType(), false); + } + + /** TIMESTAMP_NS overloads of month_floor. */ + @ExecFunction(name = "month_floor") + public static Expression monthFloorTimeStampNs(TimeStampNsLiteral date) { + return roundTimeStampNs(DATE.MONTH, date, 1, START_ORIGINAL_DAY, false); + } + + @ExecFunction(name = "month_floor") + public static Expression monthFloorTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period) { + return roundTimeStampNs(DATE.MONTH, date, period.getValue(), START_ORIGINAL_DAY, false); + } + + @ExecFunction(name = "month_floor") + public static Expression monthFloorTimeStampNs(TimeStampNsLiteral date, TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.MONTH, date, 1, origin.toJavaDateType(), false); + } + + @ExecFunction(name = "month_floor") + public static Expression monthFloorTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period, + TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.MONTH, date, period.getValue(), origin.toJavaDateType(), false); + } + + /** TIMESTAMP_NS overloads of day_floor. */ + @ExecFunction(name = "day_floor") + public static Expression dayFloorTimeStampNs(TimeStampNsLiteral date) { + return roundTimeStampNs(DATE.DAY, date, 1, START_ORIGINAL_DAY, false); + } + + @ExecFunction(name = "day_floor") + public static Expression dayFloorTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period) { + return roundTimeStampNs(DATE.DAY, date, period.getValue(), START_ORIGINAL_DAY, false); + } + + @ExecFunction(name = "day_floor") + public static Expression dayFloorTimeStampNs(TimeStampNsLiteral date, TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.DAY, date, 1, origin.toJavaDateType(), false); + } + + @ExecFunction(name = "day_floor") + public static Expression dayFloorTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period, + TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.DAY, date, period.getValue(), origin.toJavaDateType(), false); + } + + /** TIMESTAMP_NS overloads of hour_floor. */ + @ExecFunction(name = "hour_floor") + public static Expression hourFloorTimeStampNs(TimeStampNsLiteral date) { + return roundTimeStampNs(DATE.HOUR, date, 1, START_ORIGINAL_DAY, false); + } + + @ExecFunction(name = "hour_floor") + public static Expression hourFloorTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period) { + return roundTimeStampNs(DATE.HOUR, date, period.getValue(), START_ORIGINAL_DAY, false); + } + + @ExecFunction(name = "hour_floor") + public static Expression hourFloorTimeStampNs(TimeStampNsLiteral date, TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.HOUR, date, 1, origin.toJavaDateType(), false); + } + + @ExecFunction(name = "hour_floor") + public static Expression hourFloorTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period, + TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.HOUR, date, period.getValue(), origin.toJavaDateType(), false); + } + + /** TIMESTAMP_NS overloads of minute_floor. */ + @ExecFunction(name = "minute_floor") + public static Expression minuteFloorTimeStampNs(TimeStampNsLiteral date) { + return roundTimeStampNs(DATE.MINUTE, date, 1, START_ORIGINAL_DAY, false); + } + + @ExecFunction(name = "minute_floor") + public static Expression minuteFloorTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period) { + return roundTimeStampNs(DATE.MINUTE, date, period.getValue(), START_ORIGINAL_DAY, false); + } + + @ExecFunction(name = "minute_floor") + public static Expression minuteFloorTimeStampNs(TimeStampNsLiteral date, TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.MINUTE, date, 1, origin.toJavaDateType(), false); + } + + @ExecFunction(name = "minute_floor") + public static Expression minuteFloorTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period, + TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.MINUTE, date, period.getValue(), origin.toJavaDateType(), false); + } + + /** TIMESTAMP_NS overloads of second_floor. */ + @ExecFunction(name = "second_floor") + public static Expression secondFloorTimeStampNs(TimeStampNsLiteral date) { + return roundTimeStampNs(DATE.SECOND, date, 1, START_ORIGINAL_DAY, false); + } + + @ExecFunction(name = "second_floor") + public static Expression secondFloorTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period) { + return roundTimeStampNs(DATE.SECOND, date, period.getValue(), START_ORIGINAL_DAY, false); + } + + @ExecFunction(name = "second_floor") + public static Expression secondFloorTimeStampNs(TimeStampNsLiteral date, TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.SECOND, date, 1, origin.toJavaDateType(), false); + } + + @ExecFunction(name = "second_floor") + public static Expression secondFloorTimeStampNs(TimeStampNsLiteral date, IntegerLiteral period, + TimeStampNsLiteral origin) { + return roundTimeStampNs(DATE.SECOND, date, period.getValue(), origin.toJavaDateType(), false); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/AddTime.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/AddTime.java index 805495c476e589..18a202987dac17 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/AddTime.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/AddTime.java @@ -25,6 +25,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.TimeV2Type; @@ -42,6 +43,8 @@ public class AddTime extends ScalarFunction implements BinaryExpression, Explici private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, TimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, + TimeV2Type.MAX), FunctionSignature.ret(TimeV2Type.WILDCARD).args(TimeV2Type.WILDCARD, TimeV2Type.WILDCARD), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, TimeV2Type.WILDCARD) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRange.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRange.java index 8dc30b1dd517d1..4206f69b4a1155 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRange.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRange.java @@ -25,6 +25,7 @@ import org.apache.doris.nereids.types.ArrayType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -42,8 +43,12 @@ public class ArrayRange extends ScalarFunction FunctionSignature.ret(ArrayType.of(IntegerType.INSTANCE)).args(IntegerType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(ArrayType.of(IntegerType.INSTANCE)) .args(IntegerType.INSTANCE, IntegerType.INSTANCE, IntegerType.INSTANCE), + FunctionSignature.ret(ArrayType.of(TimeStampNsType.INSTANCE)) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(ArrayType.of(DateTimeV2Type.WILDCARD)) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), + FunctionSignature.ret(ArrayType.of(TimeStampNsType.INSTANCE)) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(ArrayType.of(DateTimeV2Type.WILDCARD)) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD, IntegerType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeDayUnit.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeDayUnit.java index 0090c0c871a418..89215946a375a0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeDayUnit.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeDayUnit.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.types.ArrayType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -38,6 +39,8 @@ public class ArrayRangeDayUnit extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, AlwaysNullable { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(ArrayType.of(TimeStampNsType.INSTANCE)) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(ArrayType.of(DateTimeV2Type.WILDCARD)) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD, IntegerType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeHourUnit.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeHourUnit.java index 32095e82b68495..d8b869df5b773b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeHourUnit.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeHourUnit.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.types.ArrayType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -38,6 +39,8 @@ public class ArrayRangeHourUnit extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, AlwaysNullable { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(ArrayType.of(TimeStampNsType.INSTANCE)) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(ArrayType.of(DateTimeV2Type.WILDCARD)) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD, IntegerType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeMinuteUnit.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeMinuteUnit.java index 4c08d0144e9d5d..a254f30f8a508c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeMinuteUnit.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeMinuteUnit.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.types.ArrayType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -38,6 +39,8 @@ public class ArrayRangeMinuteUnit extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, AlwaysNullable { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(ArrayType.of(TimeStampNsType.INSTANCE)) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(ArrayType.of(DateTimeV2Type.WILDCARD)) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD, IntegerType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeMonthUnit.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeMonthUnit.java index eb62df28b6967f..df363c8c18ef19 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeMonthUnit.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeMonthUnit.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.types.ArrayType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -38,6 +39,8 @@ public class ArrayRangeMonthUnit extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, AlwaysNullable { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(ArrayType.of(TimeStampNsType.INSTANCE)) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(ArrayType.of(DateTimeV2Type.WILDCARD)) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD, IntegerType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeQuarterUnit.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeQuarterUnit.java index 2f6c47de5f33ed..7ee1bb1927bb9e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeQuarterUnit.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeQuarterUnit.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.types.ArrayType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -38,6 +39,8 @@ public class ArrayRangeQuarterUnit extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, AlwaysNullable { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(ArrayType.of(TimeStampNsType.INSTANCE)) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(ArrayType.of(DateTimeV2Type.WILDCARD)) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD, IntegerType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeSecondUnit.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeSecondUnit.java index e9033aa47ec926..d17cced4d2e65d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeSecondUnit.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeSecondUnit.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.types.ArrayType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -38,6 +39,8 @@ public class ArrayRangeSecondUnit extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, AlwaysNullable { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(ArrayType.of(TimeStampNsType.INSTANCE)) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(ArrayType.of(DateTimeV2Type.WILDCARD)) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD, IntegerType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeWeekUnit.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeWeekUnit.java index 127a3de73c7caa..a1f83d3a3627a2 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeWeekUnit.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeWeekUnit.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.types.ArrayType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -38,6 +39,8 @@ public class ArrayRangeWeekUnit extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, AlwaysNullable { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(ArrayType.of(TimeStampNsType.INSTANCE)) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(ArrayType.of(DateTimeV2Type.WILDCARD)) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD, IntegerType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeYearUnit.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeYearUnit.java index 1ec1ee61c05fe1..43470e0ef3e314 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeYearUnit.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayRangeYearUnit.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.types.ArrayType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -38,6 +39,8 @@ public class ArrayRangeYearUnit extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, AlwaysNullable { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(ArrayType.of(TimeStampNsType.INSTANCE)) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(ArrayType.of(DateTimeV2Type.WILDCARD)) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD, IntegerType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Century.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Century.java index 9ed565d3d73306..4d3893dcd9ee2e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Century.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Century.java @@ -27,6 +27,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.SmallIntType; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -41,7 +42,8 @@ public class Century extends ScalarFunction private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(SmallIntType.INSTANCE).args(DateV2Type.INSTANCE), - FunctionSignature.ret(SmallIntType.INSTANCE).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(SmallIntType.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(SmallIntType.INSTANCE).args(TimeStampNsType.INSTANCE)); /** * constructor with 1 argument. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ConvertTz.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ConvertTz.java index 195ea273af90b8..5606b023987850 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ConvertTz.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ConvertTz.java @@ -34,6 +34,7 @@ import org.apache.doris.nereids.trees.expressions.shape.TernaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.VarcharType; import org.apache.doris.nereids.util.DateUtils; @@ -54,7 +55,9 @@ public class ConvertTz extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD) - .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT, VarcharType.SYSTEM_DEFAULT) + .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT, VarcharType.SYSTEM_DEFAULT) ); /** diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Date.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Date.java index 4b058ade725e1f..1540e78162af0f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Date.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Date.java @@ -27,6 +27,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -41,7 +42,8 @@ public class Date extends ScalarFunction //TODO: eliminate this function for Date input public static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(DateV2Type.INSTANCE).args(DateTimeV2Type.SYSTEM_DEFAULT) + FunctionSignature.ret(DateV2Type.INSTANCE).args(DateTimeV2Type.SYSTEM_DEFAULT), + FunctionSignature.ret(DateV2Type.INSTANCE).args(TimeStampNsType.INSTANCE) ); /** diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateDiff.java index 2d766295f649b4..ab0e1e69170712 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateDiff.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -42,6 +43,8 @@ public class DateDiff extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(IntegerType.INSTANCE) .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), + FunctionSignature.ret(IntegerType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(IntegerType.INSTANCE) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), FunctionSignature.ret(IntegerType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateFormat.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateFormat.java index 6c26a94f635cd9..5a5884d75ab709 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateFormat.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateFormat.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.VarcharType; import org.apache.doris.nereids.util.DateUtils; @@ -44,6 +45,8 @@ public class DateFormat extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD, + VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT)); /** diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateV2.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateV2.java index 69d3de3a6c9052..bdbdd21425aad7 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateV2.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateV2.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -39,7 +40,8 @@ public class DateV2 extends ScalarFunction implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullLiteral, PropagateNullable { public static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(DateV2Type.INSTANCE).args(DateTimeV2Type.SYSTEM_DEFAULT) + FunctionSignature.ret(DateV2Type.INSTANCE).args(DateTimeV2Type.SYSTEM_DEFAULT), + FunctionSignature.ret(DateV2Type.INSTANCE).args(TimeStampNsType.INSTANCE) ); /** diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayCeil.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayCeil.java index 260d3d4037a3a6..7df1790dc905be 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayCeil.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayCeil.java @@ -27,6 +27,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -41,11 +42,18 @@ public class DayCeil extends ScalarFunction implements ExplicitlyCastableSignature, PropagateNullLiteral, PropagateNullable, DateCeilFloorMonotonic { public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE, DateTimeV2Type.WILDCARD), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayFloor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayFloor.java index dece77f6ed99b7..19bf8aa440c726 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayFloor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayFloor.java @@ -27,6 +27,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -41,11 +42,18 @@ public class DayFloor extends ScalarFunction implements ExplicitlyCastableSignature, PropagateNullLiteral, PropagateNullable, DateCeilFloorMonotonic { public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE, DateTimeV2Type.WILDCARD), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayHour.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayHour.java index c67397d92d183e..d5954a9f1a5d76 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayHour.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayHour.java @@ -24,6 +24,7 @@ import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.VarcharType; import com.google.common.base.Preconditions; @@ -38,7 +39,8 @@ public class DayHour extends ScalarFunction implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(TimeStampNsType.INSTANCE)); public DayHour(Expression arg) { super("day_hour", arg); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayHourAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayHourAdd.java index f125432c5fc499..5a15cafdf864bc 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayHourAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayHourAdd.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class DayHourAdd extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, + VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayHourSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayHourSub.java index fba84e5c534bf6..55394215ddb74d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayHourSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayHourSub.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class DayHourSub extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, + VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecond.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecond.java index 2f05f8e588a07d..398cb72c7b647b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecond.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecond.java @@ -24,6 +24,7 @@ import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.VarcharType; import com.google.common.base.Preconditions; @@ -38,7 +39,8 @@ public class DayMicrosecond extends ScalarFunction implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(TimeStampNsType.INSTANCE)); public DayMicrosecond(Expression arg) { super("day_microsecond", arg); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondAdd.java index 22b319464bc08a..b56848e6793abb 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondAdd.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class DayMicrosecondAdd extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.MAX) .args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.MAX) .args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) ); @@ -80,6 +83,9 @@ public Expression withConstantArgs(Expression literal) { @Override public FunctionSignature computeSignature(FunctionSignature signature) { signature = super.computeSignature(signature); + if (signature.returnType instanceof TimeStampNsType) { + return signature; + } return signature.withArgumentType(0, DateTimeV2Type.MAX).withReturnType(DateTimeV2Type.MAX); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondSub.java index efb61c5f72ec17..197c28eb7db632 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondSub.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class DayMicrosecondSub extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.MAX) .args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.MAX) .args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) ); @@ -80,6 +83,9 @@ public Expression withConstantArgs(Expression literal) { @Override public FunctionSignature computeSignature(FunctionSignature signature) { signature = super.computeSignature(signature); + if (signature.returnType instanceof TimeStampNsType) { + return signature; + } return signature.withArgumentType(0, DateTimeV2Type.MAX).withReturnType(DateTimeV2Type.MAX); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinute.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinute.java index 46eed01bd20c36..f182aada2ae9fd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinute.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinute.java @@ -24,6 +24,7 @@ import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.VarcharType; import com.google.common.base.Preconditions; @@ -38,7 +39,8 @@ public class DayMinute extends ScalarFunction implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(TimeStampNsType.INSTANCE)); public DayMinute(Expression arg) { super("day_minute", arg); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinuteAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinuteAdd.java index a2aa28d088ac94..79deebff10e1a7 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinuteAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinuteAdd.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class DayMinuteAdd extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.WILDCARD) .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinuteSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinuteSub.java index e74dc3daf1246c..708c2ccee2ea1e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinuteSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinuteSub.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class DayMinuteSub extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.WILDCARD) .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayName.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayName.java index fe4ea295402526..6e852ce16cba68 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayName.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayName.java @@ -25,6 +25,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.VarcharType; import com.google.common.base.Preconditions; @@ -40,7 +41,8 @@ public class DayName extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateV2Type.INSTANCE), - FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(TimeStampNsType.INSTANCE)); /** * constructor with 1 argument. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayOfMonth.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayOfMonth.java index 65bc38ce305d53..07ef40c28142e9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayOfMonth.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayOfMonth.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TinyIntType; import com.google.common.base.Preconditions; @@ -43,7 +44,8 @@ public class DayOfMonth extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(TinyIntType.INSTANCE).args(DateV2Type.INSTANCE), - FunctionSignature.ret(TinyIntType.INSTANCE).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(TinyIntType.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TinyIntType.INSTANCE).args(TimeStampNsType.INSTANCE)); /** * constructor with 1 argument. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayOfWeek.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayOfWeek.java index 37608ed54deffb..1c1c3ac330eca7 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayOfWeek.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayOfWeek.java @@ -25,6 +25,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TinyIntType; import com.google.common.base.Preconditions; @@ -40,7 +41,8 @@ public class DayOfWeek extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(TinyIntType.INSTANCE).args(DateV2Type.INSTANCE), - FunctionSignature.ret(TinyIntType.INSTANCE).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(TinyIntType.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TinyIntType.INSTANCE).args(TimeStampNsType.INSTANCE)); /** * constructor with 1 argument. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayOfYear.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayOfYear.java index d6925d168ab908..917e2cf95c9dc5 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayOfYear.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayOfYear.java @@ -29,6 +29,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.SmallIntType; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -43,7 +44,8 @@ public class DayOfYear extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(SmallIntType.INSTANCE).args(DateV2Type.INSTANCE), - FunctionSignature.ret(SmallIntType.INSTANCE).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(SmallIntType.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(SmallIntType.INSTANCE).args(TimeStampNsType.INSTANCE)); /** * constructor with 1 argument. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaySecond.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaySecond.java index 78314de8708061..0cea4dc2f92132 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaySecond.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaySecond.java @@ -24,6 +24,7 @@ import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.VarcharType; import com.google.common.base.Preconditions; @@ -38,7 +39,8 @@ public class DaySecond extends ScalarFunction implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(TimeStampNsType.INSTANCE)); public DaySecond(Expression arg) { super("day_second", arg); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaySecondAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaySecondAdd.java index c3fc0542a4ca1b..a91a7d95c3542e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaySecondAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaySecondAdd.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class DaySecondAdd extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, + VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaySecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaySecondSub.java index 3c23817031df5c..a0070cb3d2bd11 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaySecondSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaySecondSub.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class DaySecondSub extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, + VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaysAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaysAdd.java index d65c33bd63339e..ffdcfea289a433 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaysAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaysAdd.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -47,6 +48,8 @@ public class DaysAdd extends ScalarFunction implements BinaryExpression, Explici private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, + IntegerType.INSTANCE), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, IntegerType.INSTANCE) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaysDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaysDiff.java index 012ad7c6399c26..7f325f478082fe 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaysDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaysDiff.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -43,6 +44,7 @@ public class DaysDiff extends ScalarFunction implements BinaryExpression, Explic private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(BigIntType.INSTANCE).args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), + FunctionSignature.ret(BigIntType.INSTANCE).args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(BigIntType.INSTANCE).args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaysSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaysSub.java index 570dda52b38c8c..e2fd64b60c801c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaysSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaysSub.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -46,6 +47,7 @@ public class DaysSub extends ScalarFunction implements BinaryExpression, Explici // without loss, we handle it by ComputeSignatureForDateArithmetic. private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, IntegerType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Field.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Field.java index 2c634c9f05d0f3..e8c068af66a4fd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Field.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Field.java @@ -34,6 +34,7 @@ import org.apache.doris.nereids.types.LargeIntType; import org.apache.doris.nereids.types.SmallIntType; import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TinyIntType; import org.apache.doris.nereids.types.VarcharType; import org.apache.doris.nereids.util.ExpressionUtils; @@ -61,6 +62,7 @@ public class Field extends ScalarFunction .varArgs(DecimalV2Type.SYSTEM_DEFAULT, DecimalV2Type.SYSTEM_DEFAULT), FunctionSignature.ret(IntegerType.INSTANCE).varArgs(DecimalV3Type.WILDCARD, DecimalV3Type.WILDCARD), FunctionSignature.ret(IntegerType.INSTANCE).varArgs(DateV2Type.INSTANCE, DateV2Type.INSTANCE), + FunctionSignature.ret(IntegerType.INSTANCE).varArgs(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(IntegerType.INSTANCE).varArgs(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), FunctionSignature.ret(IntegerType.INSTANCE).varArgs(VarcharType.SYSTEM_DEFAULT, VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(IntegerType.INSTANCE).varArgs(StringType.INSTANCE, StringType.INSTANCE) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Hour.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Hour.java index 685da58c377415..664412c4571566 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Hour.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Hour.java @@ -29,6 +29,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeV2Type; import org.apache.doris.nereids.types.TinyIntType; @@ -45,6 +46,7 @@ public class Hour extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(TinyIntType.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TinyIntType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(TinyIntType.INSTANCE).args(DateV2Type.INSTANCE), FunctionSignature.ret(IntegerType.INSTANCE).args(TimeV2Type.WILDCARD)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourCeil.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourCeil.java index 86d6cc0fc4126e..120c79d57cbff5 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourCeil.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourCeil.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -40,11 +41,18 @@ public class HourCeil extends ScalarFunction implements ExplicitlyCastableSignature, PropagateNullLiteral, PropagateNullable, DateCeilFloorMonotonic { public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE, DateTimeV2Type.WILDCARD), FunctionSignature.ret(TimeStampTzType.WILDCARD) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourFloor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourFloor.java index e27c9aaa409368..ad38612f2c1c5c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourFloor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourFloor.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -40,11 +41,18 @@ public class HourFloor extends ScalarFunction implements ExplicitlyCastableSignature, PropagateNullLiteral, PropagateNullable, DateCeilFloorMonotonic { public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE, DateTimeV2Type.WILDCARD), FunctionSignature.ret(TimeStampTzType.WILDCARD) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecond.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecond.java index 5322c6bb965a07..180c1be2e3a2c4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecond.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecond.java @@ -24,6 +24,7 @@ import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.VarcharType; import com.google.common.base.Preconditions; @@ -38,7 +39,8 @@ public class HourMicrosecond extends ScalarFunction implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(TimeStampNsType.INSTANCE)); public HourMicrosecond(Expression arg) { super("hour_microsecond", arg); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondAdd.java index d7f7c9e2a31faa..5bd21fa05d7800 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondAdd.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class HourMicrosecondAdd extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.MAX) .args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.MAX) .args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) ); @@ -80,6 +83,9 @@ public Expression withConstantArgs(Expression literal) { @Override public FunctionSignature computeSignature(FunctionSignature signature) { signature = super.computeSignature(signature); + if (signature.returnType instanceof TimeStampNsType) { + return signature; + } return signature.withArgumentType(0, DateTimeV2Type.MAX).withReturnType(DateTimeV2Type.MAX); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondSub.java index 1d43cb8e94cc5b..156e6a77aecb37 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondSub.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class HourMicrosecondSub extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.MAX) .args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.MAX) .args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) ); @@ -80,6 +83,9 @@ public Expression withConstantArgs(Expression literal) { @Override public FunctionSignature computeSignature(FunctionSignature signature) { signature = super.computeSignature(signature); + if (signature.returnType instanceof TimeStampNsType) { + return signature; + } return signature.withArgumentType(0, DateTimeV2Type.MAX).withReturnType(DateTimeV2Type.MAX); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinute.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinute.java index 122fc0daf2514a..75c756695a7ffc 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinute.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinute.java @@ -24,6 +24,7 @@ import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.VarcharType; import com.google.common.base.Preconditions; @@ -38,7 +39,8 @@ public class HourMinute extends ScalarFunction implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(TimeStampNsType.INSTANCE)); public HourMinute(Expression arg) { super("hour_minute", arg); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinuteAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinuteAdd.java index 117c7c89140f77..2f3d9ecfd064a1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinuteAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinuteAdd.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class HourMinuteAdd extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.WILDCARD) .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinuteSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinuteSub.java index 7caaf1d61aaae9..5aeaa46408acf3 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinuteSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinuteSub.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class HourMinuteSub extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.WILDCARD) .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecond.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecond.java index 74a6d957c17b5f..2921c4533cfe16 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecond.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecond.java @@ -24,6 +24,7 @@ import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.VarcharType; import com.google.common.base.Preconditions; @@ -38,7 +39,8 @@ public class HourSecond extends ScalarFunction implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(TimeStampNsType.INSTANCE)); public HourSecond(Expression arg) { super("hour_second", arg); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecondAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecondAdd.java index 056c4734b9271f..081c51a5b66520 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecondAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecondAdd.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class HourSecondAdd extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.WILDCARD) .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecondSub.java index 341a7ec98e4c3b..d19aa9dcad8c66 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecondSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecondSub.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class HourSecondSub extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.WILDCARD) .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HoursAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HoursAdd.java index b1e8b9030434c1..f05f1072099341 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HoursAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HoursAdd.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -40,7 +41,8 @@ public class HoursAdd extends ScalarFunction implements BinaryExpression, Explic PropagateNullable, DateAddSubMonotonic { public static final List SIGNATURES = ImmutableList.of(FunctionSignature - .ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + .ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), FunctionSignature + .ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, IntegerType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HoursDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HoursDiff.java index c601497c45de27..2168223878324e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HoursDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HoursDiff.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -44,6 +45,8 @@ public class HoursDiff extends ScalarFunction implements BinaryExpression, Expli public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(BigIntType.INSTANCE) .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), + FunctionSignature.ret(BigIntType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(BigIntType.INSTANCE) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HoursSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HoursSub.java index a7771c61be97bf..56ca43f588c84e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HoursSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HoursSub.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -40,7 +41,8 @@ public class HoursSub extends ScalarFunction implements BinaryExpression, Explic PropagateNullable, DateAddSubMonotonic { public static final List SIGNATURES = ImmutableList.of(FunctionSignature - .ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + .ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), FunctionSignature + .ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, IntegerType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/LastDay.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/LastDay.java index 649471b7d642b9..a6791b0c231868 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/LastDay.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/LastDay.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -40,7 +41,8 @@ public class LastDay extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE), - FunctionSignature.ret(DateV2Type.INSTANCE).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(DateV2Type.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(DateV2Type.INSTANCE).args(TimeStampNsType.INSTANCE)); /** * constructor with 1 argument. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondTimestamp.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondTimestamp.java index f8ee77230146f7..6f52509a64eded 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondTimestamp.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondTimestamp.java @@ -25,6 +25,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -38,7 +39,8 @@ public class MicroSecondTimestamp extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(BigIntType.INSTANCE).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(BigIntType.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(BigIntType.INSTANCE).args(TimeStampNsType.INSTANCE)); public MicroSecondTimestamp(Expression arg0) { super("microsecond_timestamp", arg0); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsAdd.java index c83c2f8f5edc3b..2c69152e9ad2d8 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsAdd.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -41,6 +42,7 @@ public class MicroSecondsAdd extends ScalarFunction implements BinaryExpression, private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.MAX).args(DateTimeV2Type.MAX, BigIntType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, BigIntType.INSTANCE), FunctionSignature.ret(TimeStampTzType.MAX).args(TimeStampTzType.MAX, BigIntType.INSTANCE) ); @@ -67,6 +69,9 @@ public List getSignatures() { @Override public FunctionSignature computeSignature(FunctionSignature signature) { signature = super.computeSignature(signature); + if (signature.returnType instanceof TimeStampNsType) { + return signature; + } if (signature.argumentsTypes.get(0) instanceof TimeStampTzType) { return signature.withArgumentType(0, TimeStampTzType.MAX).withReturnType(TimeStampTzType.MAX); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsDiff.java index 26081a347a05e4..97a27383dc3094 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsDiff.java @@ -27,6 +27,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -43,6 +44,8 @@ public class MicroSecondsDiff extends ScalarFunction implements BinaryExpression private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(BigIntType.INSTANCE) .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), + FunctionSignature.ret(BigIntType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(BigIntType.INSTANCE) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsSub.java index a407a945481918..b618d06c270d75 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MicroSecondsSub.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -41,6 +42,7 @@ public class MicroSecondsSub extends ScalarFunction implements BinaryExpression, private static final List SIGNATURES = ImmutableList .of(FunctionSignature.ret(DateTimeV2Type.MAX).args(DateTimeV2Type.MAX, BigIntType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, BigIntType.INSTANCE), FunctionSignature.ret(TimeStampTzType.MAX).args(TimeStampTzType.MAX, BigIntType.INSTANCE) ); @@ -67,6 +69,9 @@ public List getSignatures() { @Override public FunctionSignature computeSignature(FunctionSignature signature) { signature = super.computeSignature(signature); + if (signature.returnType instanceof TimeStampNsType) { + return signature; + } if (signature.argumentsTypes.get(0) instanceof TimeStampTzType) { return signature.withArgumentType(0, TimeStampTzType.MAX).withReturnType(TimeStampTzType.MAX); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Microsecond.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Microsecond.java index 3077ed41eeea26..248fd97cef7cb5 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Microsecond.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Microsecond.java @@ -29,6 +29,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeV2Type; import com.google.common.base.Preconditions; @@ -44,6 +45,7 @@ public class Microsecond extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(IntegerType.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(IntegerType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(IntegerType.INSTANCE).args(TimeV2Type.WILDCARD) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondTimestamp.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondTimestamp.java index 29f5d8bf9f77d0..29c3f7d01ada47 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondTimestamp.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondTimestamp.java @@ -25,6 +25,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -38,7 +39,8 @@ public class MilliSecondTimestamp extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(BigIntType.INSTANCE).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(BigIntType.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(BigIntType.INSTANCE).args(TimeStampNsType.INSTANCE)); public MilliSecondTimestamp(Expression arg0) { super("millisecond_timestamp", arg0); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsAdd.java index 4880e260eb2064..7b95fdc632ea95 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsAdd.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -41,6 +42,7 @@ public class MilliSecondsAdd extends ScalarFunction implements BinaryExpression, private static final List SIGNATURES = ImmutableList .of(FunctionSignature.ret(DateTimeV2Type.MAX).args(DateTimeV2Type.MAX, BigIntType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, BigIntType.INSTANCE), FunctionSignature.ret(TimeStampTzType.MAX).args(TimeStampTzType.MAX, BigIntType.INSTANCE) ); @@ -67,6 +69,9 @@ public List getSignatures() { @Override public FunctionSignature computeSignature(FunctionSignature signature) { signature = super.computeSignature(signature); + if (signature.returnType instanceof TimeStampNsType) { + return signature; + } if (signature.argumentsTypes.get(0) instanceof TimeStampTzType) { return signature.withArgumentType(0, TimeStampTzType.MAX).withReturnType(TimeStampTzType.MAX); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsDiff.java index 9cda6cb8e4ad2e..d2fd956866cc09 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsDiff.java @@ -27,6 +27,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -43,6 +44,8 @@ public class MilliSecondsDiff extends ScalarFunction implements BinaryExpression private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(BigIntType.INSTANCE) .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), + FunctionSignature.ret(BigIntType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(BigIntType.INSTANCE) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsSub.java index 2bf37e4b81fcc8..363d1f20df974a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MilliSecondsSub.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -41,6 +42,7 @@ public class MilliSecondsSub extends ScalarFunction implements BinaryExpression, private static final List SIGNATURES = ImmutableList .of(FunctionSignature.ret(DateTimeV2Type.MAX).args(DateTimeV2Type.MAX, BigIntType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, BigIntType.INSTANCE), FunctionSignature.ret(TimeStampTzType.MAX).args(TimeStampTzType.MAX, BigIntType.INSTANCE) ); @@ -67,6 +69,9 @@ public List getSignatures() { @Override public FunctionSignature computeSignature(FunctionSignature signature) { signature = super.computeSignature(signature); + if (signature.returnType instanceof TimeStampNsType) { + return signature; + } if (signature.argumentsTypes.get(0) instanceof TimeStampTzType) { return signature.withArgumentType(0, TimeStampTzType.MAX).withReturnType(TimeStampTzType.MAX); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Minute.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Minute.java index 3ef8c40d540b51..5685c6e2b2f6da 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Minute.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Minute.java @@ -29,6 +29,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeV2Type; import org.apache.doris.nereids.types.TinyIntType; @@ -45,6 +46,7 @@ public class Minute extends ScalarFunction private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(TinyIntType.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TinyIntType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(TinyIntType.INSTANCE).args(DateV2Type.INSTANCE), FunctionSignature.ret(TinyIntType.INSTANCE).args(TimeV2Type.WILDCARD)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteCeil.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteCeil.java index 8896553e609f10..bed0f2cd7eaf7e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteCeil.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteCeil.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -40,11 +41,18 @@ public class MinuteCeil extends ScalarFunction implements ExplicitlyCastableSignature, PropagateNullLiteral, PropagateNullable, DateCeilFloorMonotonic { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE, DateTimeV2Type.WILDCARD), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteFloor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteFloor.java index ebcd13ee2b4371..b6e9eba2be7d6c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteFloor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteFloor.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -40,11 +41,18 @@ public class MinuteFloor extends ScalarFunction implements ExplicitlyCastableSignature, PropagateNullLiteral, PropagateNullable, DateCeilFloorMonotonic { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE, DateTimeV2Type.WILDCARD), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecond.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecond.java index f4a6e4e0951f91..dba76fb03c6bcc 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecond.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecond.java @@ -24,6 +24,7 @@ import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.VarcharType; import com.google.common.base.Preconditions; @@ -38,7 +39,8 @@ public class MinuteMicrosecond extends ScalarFunction implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(TimeStampNsType.INSTANCE)); public MinuteMicrosecond(Expression arg) { super("minute_microsecond", arg); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondAdd.java index 135666d6d52cf4..96c8bb37d40777 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondAdd.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class MinuteMicrosecondAdd extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.MAX) .args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.MAX) .args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) ); @@ -80,6 +83,9 @@ public Expression withConstantArgs(Expression literal) { @Override public FunctionSignature computeSignature(FunctionSignature signature) { signature = super.computeSignature(signature); + if (signature.returnType instanceof TimeStampNsType) { + return signature; + } return signature.withArgumentType(0, DateTimeV2Type.MAX).withReturnType(DateTimeV2Type.MAX); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondSub.java index 45b7272d505f46..b9ebfdf8654245 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondSub.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class MinuteMicrosecondSub extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.MAX) .args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.MAX) .args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) ); @@ -80,6 +83,9 @@ public Expression withConstantArgs(Expression literal) { @Override public FunctionSignature computeSignature(FunctionSignature signature) { signature = super.computeSignature(signature); + if (signature.returnType instanceof TimeStampNsType) { + return signature; + } return signature.withArgumentType(0, DateTimeV2Type.MAX).withReturnType(DateTimeV2Type.MAX); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecond.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecond.java index 18499e98e64e4c..e5567debd98894 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecond.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecond.java @@ -24,6 +24,7 @@ import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.VarcharType; import com.google.common.base.Preconditions; @@ -38,7 +39,8 @@ public class MinuteSecond extends ScalarFunction implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(TimeStampNsType.INSTANCE)); public MinuteSecond(Expression arg) { super("minute_second", arg); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecondAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecondAdd.java index 225ceb3ae80548..14dd94cdf2297f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecondAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecondAdd.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class MinuteSecondAdd extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, + VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecondSub.java index c525d696fa1e82..e8d8d248631190 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecondSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecondSub.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class MinuteSecondSub extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, + VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinutesAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinutesAdd.java index b5d92f87df1595..6b0bd7166b6fd8 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinutesAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinutesAdd.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -40,7 +41,8 @@ public class MinutesAdd extends ScalarFunction implements BinaryExpression, Expl PropagateNullable, DateAddSubMonotonic { public static final List SIGNATURES = ImmutableList.of(FunctionSignature - .ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, BigIntType.INSTANCE), + .ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, BigIntType.INSTANCE), FunctionSignature + .ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, BigIntType.INSTANCE), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, BigIntType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinutesDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinutesDiff.java index f1a320932f09d4..ce2ae4ba3e047b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinutesDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinutesDiff.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -44,6 +45,8 @@ public class MinutesDiff extends ScalarFunction implements BinaryExpression, Exp private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(BigIntType.INSTANCE) .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), + FunctionSignature.ret(BigIntType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(BigIntType.INSTANCE) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinutesSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinutesSub.java index 5319dc2a4ad016..e124e0feab297c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinutesSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinutesSub.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -40,7 +41,8 @@ public class MinutesSub extends ScalarFunction implements BinaryExpression, Expl PropagateNullable, DateAddSubMonotonic { public static final List SIGNATURES = ImmutableList.of(FunctionSignature - .ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, BigIntType.INSTANCE), + .ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, BigIntType.INSTANCE), FunctionSignature + .ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, BigIntType.INSTANCE), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, BigIntType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Month.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Month.java index 60acc9b97ffcf0..550d9c465ad90a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Month.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Month.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TinyIntType; import com.google.common.base.Preconditions; @@ -43,7 +44,8 @@ public class Month extends ScalarFunction private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(TinyIntType.INSTANCE).args(DateV2Type.INSTANCE), - FunctionSignature.ret(TinyIntType.INSTANCE).args(DateTimeV2Type.WILDCARD) + FunctionSignature.ret(TinyIntType.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TinyIntType.INSTANCE).args(TimeStampNsType.INSTANCE) ); /** diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthCeil.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthCeil.java index 0dc10ad8ab7532..ca8ae53c9e6cf9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthCeil.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthCeil.java @@ -27,6 +27,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -41,11 +42,18 @@ public class MonthCeil extends ScalarFunction implements ExplicitlyCastableSignature, PropagateNullLiteral, PropagateNullable, DateCeilFloorMonotonic { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE, DateTimeV2Type.WILDCARD), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthFloor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthFloor.java index 8fe2d8aa3b9b8c..24192c6e98ceaa 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthFloor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthFloor.java @@ -27,6 +27,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -41,11 +42,18 @@ public class MonthFloor extends ScalarFunction implements ExplicitlyCastableSignature, PropagateNullLiteral, PropagateNullable, DateCeilFloorMonotonic { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE, DateTimeV2Type.WILDCARD), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthName.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthName.java index 8bec9d4cf98317..f8319cfc77da7a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthName.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthName.java @@ -25,6 +25,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.VarcharType; import com.google.common.base.Preconditions; @@ -40,7 +41,8 @@ public class MonthName extends ScalarFunction private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateV2Type.INSTANCE), - FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(TimeStampNsType.INSTANCE)); /** * constructor with 1 argument. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthsAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthsAdd.java index e80acdd04cfe76..e9f44840d78f9c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthsAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthsAdd.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -47,6 +48,8 @@ public class MonthsAdd extends ScalarFunction implements BinaryExpression, Expli private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, + IntegerType.INSTANCE), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, IntegerType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthsDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthsDiff.java index 7c11156861b87f..f5caf6f65e1a73 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthsDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthsDiff.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -44,6 +45,8 @@ public class MonthsDiff extends ScalarFunction implements BinaryExpression, Expl private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(BigIntType.INSTANCE) .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), + FunctionSignature.ret(BigIntType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(BigIntType.INSTANCE) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthsSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthsSub.java index 5ba6c743453be3..da58e6270a6166 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthsSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MonthsSub.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -47,6 +48,8 @@ public class MonthsSub extends ScalarFunction implements BinaryExpression, Expli private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, + IntegerType.INSTANCE), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, IntegerType.INSTANCE) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Quarter.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Quarter.java index c098d068c85eed..60cbe488b84542 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Quarter.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Quarter.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TinyIntType; import com.google.common.base.Preconditions; @@ -43,6 +44,7 @@ public class Quarter extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(TinyIntType.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TinyIntType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(TinyIntType.INSTANCE).args(DateV2Type.INSTANCE)); /** diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuarterCeil.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuarterCeil.java index 28e19e85e1f8cf..d679bc11939ede 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuarterCeil.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuarterCeil.java @@ -27,6 +27,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -41,11 +42,18 @@ public class QuarterCeil extends ScalarFunction implements ExplicitlyCastableSignature, PropagateNullLiteral, PropagateNullable, DateCeilFloorMonotonic { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE, DateTimeV2Type.WILDCARD), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuarterFloor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuarterFloor.java index 026aaef6f863f5..1ba13be52bc7e2 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuarterFloor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuarterFloor.java @@ -27,6 +27,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -41,11 +42,18 @@ public class QuarterFloor extends ScalarFunction implements ExplicitlyCastableSignature, PropagateNullLiteral, PropagateNullable, DateCeilFloorMonotonic { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE, DateTimeV2Type.WILDCARD), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuartersAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuartersAdd.java index 4856a1b68820d1..7e9865c4a5dfb1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuartersAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuartersAdd.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -47,6 +48,8 @@ public class QuartersAdd extends ScalarFunction implements BinaryExpression, Exp private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, + IntegerType.INSTANCE), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, IntegerType.INSTANCE) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuartersDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuartersDiff.java index ec8f889baa5621..2ecfcb78a1ad6a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuartersDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuartersDiff.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -44,6 +45,8 @@ public class QuartersDiff extends ScalarFunction implements BinaryExpression, Ex private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(BigIntType.INSTANCE) .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), + FunctionSignature.ret(BigIntType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(BigIntType.INSTANCE) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuartersSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuartersSub.java index 941657d0c24d9e..d56bab920480f6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuartersSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/QuartersSub.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -47,6 +48,8 @@ public class QuartersSub extends ScalarFunction implements BinaryExpression, Exp private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, + IntegerType.INSTANCE), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, IntegerType.INSTANCE) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Second.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Second.java index d572547a0dff6c..7bbcacf645139f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Second.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Second.java @@ -29,6 +29,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeV2Type; import org.apache.doris.nereids.types.TinyIntType; @@ -45,6 +46,7 @@ public class Second extends ScalarFunction private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(TinyIntType.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TinyIntType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(TinyIntType.INSTANCE).args(DateV2Type.INSTANCE), FunctionSignature.ret(TinyIntType.INSTANCE).args(TimeV2Type.WILDCARD)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondCeil.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondCeil.java index 6cd0f37470a6a0..3aaa1bcbc927fc 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondCeil.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondCeil.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -40,11 +41,18 @@ public class SecondCeil extends ScalarFunction implements ExplicitlyCastableSignature, PropagateNullLiteral, PropagateNullable, DateCeilFloorMonotonic { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE, DateTimeV2Type.WILDCARD), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondFloor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondFloor.java index 0731e50cbc3499..fc8e8a579e6603 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondFloor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondFloor.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -40,11 +41,18 @@ public class SecondFloor extends ScalarFunction implements ExplicitlyCastableSignature, PropagateNullLiteral, PropagateNullable, DateCeilFloorMonotonic { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE, DateTimeV2Type.WILDCARD), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecond.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecond.java index f4e6c047bfff24..f521e0ff89119b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecond.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecond.java @@ -24,6 +24,7 @@ import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.VarcharType; import com.google.common.base.Preconditions; @@ -38,7 +39,8 @@ public class SecondMicrosecond extends ScalarFunction implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(TimeStampNsType.INSTANCE)); public SecondMicrosecond(Expression arg) { super("second_microsecond", arg); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecondAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecondAdd.java index 8411699aedf2f9..83e32fef0f6fce 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecondAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecondAdd.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class SecondMicrosecondAdd extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.MAX).args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, + VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.MAX).args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) ); @@ -80,6 +83,9 @@ public Expression withConstantArgs(Expression literal) { @Override public FunctionSignature computeSignature(FunctionSignature signature) { signature = super.computeSignature(signature); + if (signature.returnType instanceof TimeStampNsType) { + return signature; + } if (signature.argumentsTypes.get(0) instanceof TimeStampTzType) { return signature.withArgumentType(0, TimeStampTzType.MAX).withReturnType(TimeStampTzType.MAX); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecondSub.java index af4350f28f26ba..303f4bdcad6a05 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecondSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecondSub.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class SecondMicrosecondSub extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.MAX).args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, + VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.MAX).args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) ); @@ -80,6 +83,9 @@ public Expression withConstantArgs(Expression literal) { @Override public FunctionSignature computeSignature(FunctionSignature signature) { signature = super.computeSignature(signature); + if (signature.returnType instanceof TimeStampNsType) { + return signature; + } if (signature.argumentsTypes.get(0) instanceof TimeStampTzType) { return signature.withArgumentType(0, TimeStampTzType.MAX).withReturnType(TimeStampTzType.MAX); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondTimestamp.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondTimestamp.java index c9721e2fa5b0de..abee821b60e009 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondTimestamp.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondTimestamp.java @@ -25,6 +25,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -38,7 +39,8 @@ public class SecondTimestamp extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(BigIntType.INSTANCE).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(BigIntType.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(BigIntType.INSTANCE).args(TimeStampNsType.INSTANCE)); public SecondTimestamp(Expression arg0) { super("second_timestamp", arg0); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondsAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondsAdd.java index 07b1ff0823c0cd..359e49d60635c9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondsAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondsAdd.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -40,7 +41,8 @@ public class SecondsAdd extends ScalarFunction implements BinaryExpression, Expl PropagateNullable, DateAddSubMonotonic { public static final List SIGNATURES = ImmutableList.of(FunctionSignature - .ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, BigIntType.INSTANCE), + .ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, BigIntType.INSTANCE), FunctionSignature + .ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, BigIntType.INSTANCE), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, BigIntType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondsDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondsDiff.java index bb7df199d284ca..dfc6623b591641 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondsDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondsDiff.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -44,6 +45,8 @@ public class SecondsDiff extends ScalarFunction implements BinaryExpression, Exp private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(BigIntType.INSTANCE) .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), + FunctionSignature.ret(BigIntType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(BigIntType.INSTANCE) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondsSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondsSub.java index 3bdecf6e60e97e..cb99957da0c26e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondsSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondsSub.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -40,7 +41,8 @@ public class SecondsSub extends ScalarFunction implements BinaryExpression, Expl PropagateNullable, DateAddSubMonotonic { public static final List SIGNATURES = ImmutableList.of(FunctionSignature - .ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, BigIntType.INSTANCE), + .ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, BigIntType.INSTANCE), FunctionSignature + .ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, BigIntType.INSTANCE), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, BigIntType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SubTime.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SubTime.java index 99505a79c09c90..acce4bb1d215d7 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SubTime.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SubTime.java @@ -25,6 +25,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.TimeV2Type; @@ -42,6 +43,8 @@ public class SubTime extends ScalarFunction implements BinaryExpression, Explici private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, TimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, + TimeV2Type.MAX), FunctionSignature.ret(TimeV2Type.WILDCARD).args(TimeV2Type.WILDCARD, TimeV2Type.WILDCARD), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, TimeV2Type.WILDCARD) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Time.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Time.java index a04771e50e7005..6707b4c89991a0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Time.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Time.java @@ -24,6 +24,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeV2Type; import com.google.common.base.Preconditions; @@ -38,7 +39,8 @@ public class Time extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(TimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(TimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeV2Type.MAX).args(TimeStampNsType.INSTANCE)); /** * constructor with 1 argument. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/TimeDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/TimeDiff.java index a25ce2d45f84bb..ca6dfa88c3a010 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/TimeDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/TimeDiff.java @@ -25,6 +25,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.TimeV2Type; @@ -42,6 +43,8 @@ public class TimeDiff extends ScalarFunction private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(TimeV2Type.WILDCARD) .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), + FunctionSignature.ret(TimeV2Type.MAX) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(TimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), FunctionSignature.ret(TimeV2Type.SYSTEM_DEFAULT).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE)); @@ -80,6 +83,12 @@ public R accept(ExpressionVisitor visitor, C context) { @Override public FunctionSignature computeSignature(FunctionSignature signature) { signature = super.computeSignature(signature); + // TIMEV2 stores at most microseconds. A TIMESTAMP_NS operand therefore fixes the result + // at TIMEV2(6); do not feed its scale 9 into TimeV2Type.of(). + if (getArgument(0).getDataType() instanceof TimeStampNsType + || getArgument(1).getDataType() instanceof TimeStampNsType) { + return signature.withReturnType(TimeV2Type.MAX); + } boolean useTimev2 = false; int scale = 0; if (getArgument(0).getDataType() instanceof DateTimeV2Type) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/TimeFormat.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/TimeFormat.java index 6c96683e29df68..12b08ce1facec5 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/TimeFormat.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/TimeFormat.java @@ -27,6 +27,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeV2Type; import org.apache.doris.nereids.types.VarcharType; import org.apache.doris.nereids.util.DateUtils; @@ -46,7 +47,9 @@ public class TimeFormat extends ScalarFunction FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT) .args(TimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT) - .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT) + .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT) + .args(TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT) ); /** diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Timestamp.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Timestamp.java index b79152982ea796..e8850f7c579770 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Timestamp.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Timestamp.java @@ -23,6 +23,7 @@ import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeV2Type; import com.google.common.base.Preconditions; @@ -40,7 +41,9 @@ public class Timestamp extends ScalarFunction // ScalarType.getDefaultDateType() public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD), - FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, TimeV2Type.WILDCARD) + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE), + FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, TimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, TimeV2Type.WILDCARD) ); /** diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToDate.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToDate.java index 2bc2014822a59c..ad875bc1a001e0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToDate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToDate.java @@ -27,6 +27,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -40,7 +41,8 @@ public class ToDate extends ScalarFunction implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable, PropagateNullLiteral, Monotonic { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(DateV2Type.INSTANCE).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(DateV2Type.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(DateV2Type.INSTANCE).args(TimeStampNsType.INSTANCE)); /** * constructor with 1 argument. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToDateV2.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToDateV2.java index 31762008d16c5d..d0852c09ea4895 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToDateV2.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToDateV2.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -39,7 +40,8 @@ public class ToDateV2 extends ScalarFunction implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable, PropagateNullLiteral { public static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(DateV2Type.INSTANCE).args(DateTimeV2Type.WILDCARD) + FunctionSignature.ret(DateV2Type.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(DateV2Type.INSTANCE).args(TimeStampNsType.INSTANCE) ); /** diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToDays.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToDays.java index 9308fd5556c9fb..522b4181414cfe 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToDays.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToDays.java @@ -25,6 +25,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -38,7 +39,8 @@ public class ToDays extends ScalarFunction implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(IntegerType.INSTANCE).args(DateV2Type.INSTANCE) + FunctionSignature.ret(IntegerType.INSTANCE).args(DateV2Type.INSTANCE), + FunctionSignature.ret(IntegerType.INSTANCE).args(TimeStampNsType.INSTANCE) ); /** diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToIso8601.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToIso8601.java index 282d5183ba4b04..619e80f2d79ec0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToIso8601.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToIso8601.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -41,6 +42,7 @@ public class ToIso8601 extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(StringType.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(StringType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(StringType.INSTANCE).args(DateV2Type.INSTANCE), FunctionSignature.ret(StringType.INSTANCE).args(TimeStampTzType.WILDCARD) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToJson.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToJson.java index a6e571c23231c6..8188e285a7dd65 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToJson.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToJson.java @@ -40,6 +40,7 @@ import org.apache.doris.nereids.types.NullType; import org.apache.doris.nereids.types.SmallIntType; import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeV2Type; import org.apache.doris.nereids.types.TinyIntType; @@ -66,6 +67,7 @@ public class ToJson extends ScalarFunction FunctionSignature.ret(JsonType.INSTANCE).args(DoubleType.INSTANCE), FunctionSignature.ret(JsonType.INSTANCE).args(DecimalV3Type.WILDCARD), FunctionSignature.ret(JsonType.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(JsonType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(JsonType.INSTANCE).args(DateV2Type.INSTANCE), FunctionSignature.ret(JsonType.INSTANCE).args(IPv4Type.INSTANCE), FunctionSignature.ret(JsonType.INSTANCE).args(IPv6Type.INSTANCE), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToMonday.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToMonday.java index 101b7b6f46d81e..734c5d4597197e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToMonday.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToMonday.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -40,7 +41,8 @@ public class ToMonday extends ScalarFunction private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE), - FunctionSignature.ret(DateV2Type.INSTANCE).args(DateTimeV2Type.WILDCARD) + FunctionSignature.ret(DateV2Type.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(DateV2Type.INSTANCE).args(TimeStampNsType.INSTANCE) ); /** diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToSeconds.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToSeconds.java index 02a601ca5c41c0..f1a421253a03d4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToSeconds.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ToSeconds.java @@ -25,6 +25,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -38,7 +39,8 @@ public class ToSeconds extends ScalarFunction implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(BigIntType.INSTANCE).args(DateTimeV2Type.WILDCARD) + FunctionSignature.ret(BigIntType.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(BigIntType.INSTANCE).args(TimeStampNsType.INSTANCE) ); /** diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/UnixTimestamp.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/UnixTimestamp.java index 9dddf56505d91f..d87f48ebfeeb61 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/UnixTimestamp.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/UnixTimestamp.java @@ -32,6 +32,7 @@ import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.DecimalV3Type; import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.VarcharType; import com.google.common.base.Preconditions; @@ -48,6 +49,7 @@ public class UnixTimestamp extends ScalarFunction private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(BigIntType.INSTANCE).args(), FunctionSignature.ret(DecimalV3Type.WILDCARD).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(DecimalV3Type.WILDCARD).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE), FunctionSignature.ret(DecimalV3Type.createDecimalV3Type(18, 6)).args(VarcharType.SYSTEM_DEFAULT, VarcharType.SYSTEM_DEFAULT), @@ -91,6 +93,9 @@ public FunctionSignature computeSignature(FunctionSignature signature) { if (argType0.isDateTimeV2Type()) { int scale = ((DateTimeV2Type) argType0).getScale(); return signature.withReturnType(DecimalV3Type.createDecimalV3Type(12 + scale, scale)); + } else if (argType0.isTimeStampNsType()) { + int scale = TimeStampNsType.SCALE; + return signature.withReturnType(DecimalV3Type.createDecimalV3Type(12 + scale, scale)); } else if (argType0.isStringLikeType()) { return signature.withReturnType(DecimalV3Type.createDecimalV3Type(18, 6)); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Week.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Week.java index 5815ad567865ca..3e942b2b958295 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Week.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Week.java @@ -25,6 +25,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TinyIntType; import com.google.common.base.Preconditions; @@ -42,7 +43,9 @@ public class Week extends ScalarFunction FunctionSignature.ret(TinyIntType.INSTANCE).args(DateV2Type.INSTANCE), FunctionSignature.ret(TinyIntType.INSTANCE).args(DateV2Type.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(TinyIntType.INSTANCE).args(DateTimeV2Type.WILDCARD), - FunctionSignature.ret(TinyIntType.INSTANCE).args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE)); + FunctionSignature.ret(TinyIntType.INSTANCE).args(TimeStampNsType.INSTANCE), + FunctionSignature.ret(TinyIntType.INSTANCE).args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TinyIntType.INSTANCE).args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE)); /** * constructor with 1 argument. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeekCeil.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeekCeil.java index a88751ea1ff297..cf76ff68346af8 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeekCeil.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeekCeil.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -40,11 +41,18 @@ public class WeekCeil extends ScalarFunction implements ExplicitlyCastableSignature, PropagateNullLiteral, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE, DateTimeV2Type.WILDCARD), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeekFloor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeekFloor.java index b2e0a916a82886..0a297519b1330d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeekFloor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeekFloor.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -40,11 +41,18 @@ public class WeekFloor extends ScalarFunction implements ExplicitlyCastableSignature, PropagateNullLiteral, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE, DateTimeV2Type.WILDCARD), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeekOfYear.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeekOfYear.java index 04a704bf9a6c08..a1091a9473cbc2 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeekOfYear.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeekOfYear.java @@ -25,6 +25,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TinyIntType; import com.google.common.base.Preconditions; @@ -40,7 +41,8 @@ public class WeekOfYear extends ScalarFunction private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(TinyIntType.INSTANCE).args(DateV2Type.INSTANCE), - FunctionSignature.ret(TinyIntType.INSTANCE).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(TinyIntType.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TinyIntType.INSTANCE).args(TimeStampNsType.INSTANCE)); /** * constructor with 1 argument. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Weekday.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Weekday.java index 56dc20b97cb702..caa15136147c53 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Weekday.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Weekday.java @@ -25,6 +25,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TinyIntType; import com.google.common.base.Preconditions; @@ -40,7 +41,8 @@ public class Weekday extends ScalarFunction private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(TinyIntType.INSTANCE).args(DateV2Type.INSTANCE), - FunctionSignature.ret(TinyIntType.INSTANCE).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(TinyIntType.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TinyIntType.INSTANCE).args(TimeStampNsType.INSTANCE)); /** * constructor with 1 argument. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeeksAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeeksAdd.java index abd397b832261d..e0ee5abe736997 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeeksAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeeksAdd.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -47,6 +48,8 @@ public class WeeksAdd extends ScalarFunction implements BinaryExpression, Explic private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, + IntegerType.INSTANCE), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, IntegerType.INSTANCE) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeeksDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeeksDiff.java index 771d43d2cb3da5..e00616dac4d120 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeeksDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeeksDiff.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -44,6 +45,8 @@ public class WeeksDiff extends ScalarFunction implements BinaryExpression, Expli private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(BigIntType.INSTANCE) .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), + FunctionSignature.ret(BigIntType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(BigIntType.INSTANCE) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeeksSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeeksSub.java index b75ff7eb445764..18dd1d4880b615 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeeksSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WeeksSub.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -47,6 +48,8 @@ public class WeeksSub extends ScalarFunction implements BinaryExpression, Explic private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, + IntegerType.INSTANCE), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, IntegerType.INSTANCE) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WidthBucket.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WidthBucket.java index f789955b72a744..499fccb3db0e4a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WidthBucket.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/WidthBucket.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.types.FloatType; import org.apache.doris.nereids.types.IntegerType; import org.apache.doris.nereids.types.SmallIntType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TinyIntType; import com.google.common.base.Preconditions; @@ -40,6 +41,8 @@ */ public class WidthBucket extends ScalarFunction implements ExplicitlyCastableSignature, PropagateNullable { public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(BigIntType.INSTANCE).args(TimeStampNsType.INSTANCE, + TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE, TinyIntType.INSTANCE), FunctionSignature.ret(BigIntType.INSTANCE).args(DoubleType.INSTANCE, DoubleType.INSTANCE, DoubleType.INSTANCE, TinyIntType.INSTANCE), FunctionSignature.ret(BigIntType.INSTANCE).args(FloatType.INSTANCE, diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Year.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Year.java index a811cc3b8d0efa..c5d2fd22e00e6a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Year.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Year.java @@ -27,6 +27,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.SmallIntType; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -41,7 +42,8 @@ public class Year extends ScalarFunction private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(SmallIntType.INSTANCE).args(DateV2Type.INSTANCE), - FunctionSignature.ret(SmallIntType.INSTANCE).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(SmallIntType.INSTANCE).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(SmallIntType.INSTANCE).args(TimeStampNsType.INSTANCE)); /** * constructor with 1 argument. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearCeil.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearCeil.java index 358227c3677496..6ed9a95f313366 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearCeil.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearCeil.java @@ -27,6 +27,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -41,11 +42,18 @@ public class YearCeil extends ScalarFunction implements ExplicitlyCastableSignature, PropagateNullLiteral, PropagateNullable, DateCeilFloorMonotonic { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE, DateTimeV2Type.WILDCARD), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearFloor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearFloor.java index 7ba43fb29fffe9..5ff41ce8f73197 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearFloor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearFloor.java @@ -27,6 +27,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -41,11 +42,18 @@ public class YearFloor extends ScalarFunction implements ExplicitlyCastableSignature, PropagateNullLiteral, PropagateNullable, DateCeilFloorMonotonic { private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE, DateTimeV2Type.WILDCARD), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonth.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonth.java index 04816fb2a1db61..e61e2754ad11ce 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonth.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonth.java @@ -24,6 +24,7 @@ import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.VarcharType; import com.google.common.base.Preconditions; @@ -38,7 +39,8 @@ public class YearMonth extends ScalarFunction implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { private static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD), + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(TimeStampNsType.INSTANCE)); /** * constructor with 1 argument. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonthAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonthAdd.java index 872654e2e4bdd3..49f52d7a6ccbe9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonthAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonthAdd.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class YearMonthAdd extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.WILDCARD) .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonthSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonthSub.java index fe3d64ae240653..2dd05536cf33ec 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonthSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonthSub.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.VarcharType; @@ -43,6 +44,8 @@ public class YearMonthSub extends ScalarFunction public static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD) .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampNsType.INSTANCE) + .args(TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT), FunctionSignature.ret(TimeStampTzType.WILDCARD) .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearWeek.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearWeek.java index 2c68a745c45ab7..632dd951e9440e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearWeek.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearWeek.java @@ -27,6 +27,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -43,7 +44,9 @@ public class YearWeek extends ScalarFunction FunctionSignature.ret(IntegerType.INSTANCE).args(DateV2Type.INSTANCE), FunctionSignature.ret(IntegerType.INSTANCE).args(DateV2Type.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(IntegerType.INSTANCE).args(DateTimeV2Type.WILDCARD), - FunctionSignature.ret(IntegerType.INSTANCE).args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE)); + FunctionSignature.ret(IntegerType.INSTANCE).args(TimeStampNsType.INSTANCE), + FunctionSignature.ret(IntegerType.INSTANCE).args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(IntegerType.INSTANCE).args(TimeStampNsType.INSTANCE, IntegerType.INSTANCE)); /** * constructor with 1 argument. diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsAdd.java index 38361688ef1636..d09e3d4c517ba3 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsAdd.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsAdd.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -47,6 +48,8 @@ public class YearsAdd extends ScalarFunction implements BinaryExpression, Explic private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, + IntegerType.INSTANCE), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, IntegerType.INSTANCE) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsDiff.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsDiff.java index da227338e0ad0c..650d57ea5ba72e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsDiff.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsDiff.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -44,6 +45,8 @@ public class YearsDiff extends ScalarFunction implements BinaryExpression, Expli private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(BigIntType.INSTANCE) .args(TimeStampTzType.WILDCARD, TimeStampTzType.WILDCARD), + FunctionSignature.ret(BigIntType.INSTANCE) + .args(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), FunctionSignature.ret(BigIntType.INSTANCE) .args(DateTimeV2Type.WILDCARD, DateTimeV2Type.WILDCARD), FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE, DateV2Type.INSTANCE)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsSub.java index 140c4e647dc95c..cfd373ba70acd1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsSub.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearsSub.java @@ -28,6 +28,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import com.google.common.base.Preconditions; @@ -47,6 +48,8 @@ public class YearsSub extends ScalarFunction implements BinaryExpression, Explic private static final List SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, IntegerType.INSTANCE), + FunctionSignature.ret(TimeStampNsType.INSTANCE).args(TimeStampNsType.INSTANCE, + IntegerType.INSTANCE), FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE, IntegerType.INSTANCE), FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, IntegerType.INSTANCE) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/RequireTrivialTypes.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/RequireTrivialTypes.java index c868f3501b5bff..074b13dab7dca6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/RequireTrivialTypes.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/RequireTrivialTypes.java @@ -32,6 +32,7 @@ import org.apache.doris.nereids.types.LargeIntType; import org.apache.doris.nereids.types.SmallIntType; import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.TimeV2Type; import org.apache.doris.nereids.types.TinyIntType; @@ -61,6 +62,7 @@ public interface RequireTrivialTypes { DateTimeType.INSTANCE, DateV2Type.INSTANCE, DateTimeV2Type.WILDCARD, + TimeStampNsType.INSTANCE, TimeV2Type.WILDCARD, TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT, diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java index 3d1f5017be3b14..3cc57289e95b3b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java @@ -20,12 +20,14 @@ import org.apache.doris.analysis.LiteralExpr; import org.apache.doris.catalog.Type; import org.apache.doris.nereids.exceptions.AnalysisException; +import org.apache.doris.nereids.exceptions.CastException; import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DataType; import org.apache.doris.nereids.types.DateTimeType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.coercion.DateLikeType; import org.apache.doris.nereids.util.DateTimeFormatterUtils; import org.apache.doris.nereids.util.DateUtils; @@ -148,6 +150,10 @@ private static boolean isPunctuation(char c) { } static Result normalize(String s) { + return normalize(s, 7); + } + + private static Result normalize(String s, int maxFractionDigits) { // merge consecutive space if (s.contains(" ")) { s = s.replaceAll(" +", " "); @@ -254,14 +260,14 @@ static Result normalize(String s) { sb.append(":00"); } - // parse MicroSecond - // Keep up to 7 digits at most, 7th digit is use for overflow. + // Legacy temporal literals keep six microsecond digits plus one rounding guard. The + // TIMESTAMP_NS parser requests nine nanosecond digits plus one rounding guard. int j = i; if (partNumber == 6 && i < s.length() && s.charAt(i) == '.') { sb.append(s.charAt(i)); i += 1; while (i < s.length() && Character.isDigit(s.charAt(i))) { - if (i - j <= 7) { + if (i - j <= maxFractionDigits) { sb.append(s.charAt(i)); } i += 1; @@ -297,6 +303,10 @@ public static Result parseDateLiteral(String s, /** parseDateTime */ public static Result parseDateTime(String s) { + return parseDateTime(s, 7); + } + + static Result parseDateTime(String s, int maxFractionDigits) { String originalString = s; try { // fast parse '2022-01-01' @@ -329,6 +339,7 @@ public static Result parseDateTime(String s } if (!containsPunctuation) { s = normalizeBasic(s); + s = DateUtils.truncateFractionalSecondForJavaParser(s); // mysql reject "20200219 010101" "200219 010101", can't use ' ' spilt basic date time. if (!s.contains("T")) { @@ -339,11 +350,12 @@ public static Result parseDateTime(String s return Result.ok(dateTime); } - Result normalizeResult = normalize(s); + Result normalizeResult = normalize(s, maxFractionDigits); if (normalizeResult.isError()) { return normalizeResult.cast(); } s = normalizeResult.get(); + s = DateUtils.truncateFractionalSecondForJavaParser(s); if (!s.contains(" ")) { dateTime = DateTimeFormatterUtils.ZONE_DATE_FORMATTER.parse(s); @@ -472,10 +484,8 @@ public int compareTo(ComparableLiteral other) { return cmp; } - long thisMicrosecond = this instanceof DateTimeV2Literal ? ((DateTimeV2Literal) this).getMicroSecond() : 0L; - long otherMicrosecond = other instanceof DateTimeV2Literal - ? ((DateTimeV2Literal) other).getMicroSecond() : 0L; - return Long.compare(thisMicrosecond, otherMicrosecond); + return Long.compare(getFractionalSecondInNanoseconds(), + ((DateLiteral) other).getFractionalSecondInNanoseconds()); } if (other instanceof NullLiteral) { return 1; @@ -500,6 +510,21 @@ public long getDay() { return day; } + /** Return the time of day in nanoseconds; DATE literals have no time part. */ + public long getTimePartInNanoseconds() { + return 0; + } + + /** Return the fractional second in nanoseconds; DATE literals have no fractional part. */ + public long getFractionalSecondInNanoseconds() { + return 0; + } + + /** DATE values represent the beginning of a day. Datetime subclasses override this as needed. */ + public boolean isMidnight() { + return true; + } + public int getDayOfYear() { if (year == 0 && month == 3 && (day == 1 || day == 2)) { return toJavaDateType().getDayOfYear() - 1; @@ -622,6 +647,12 @@ protected Expression uncheckedCastTo(DataType targetType) throws AnalysisExcepti return new FloatLiteral(value); } else if (targetType.isDoubleType()) { return new DoubleLiteral(value); + } else if (targetType instanceof TimeStampNsType) { + try { + return new TimeStampNsLiteral(year, month, day, 0, 0, 0, 0); + } catch (AnalysisException e) { + throw new CastException(e.getMessage(), e); + } } else if (targetType.isDateTimeV2Type()) { return new DateTimeV2Literal((DateTimeV2Type) targetType, year, month, day, 0, 0, 0, 0); } else if (targetType.isDateTimeType()) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteral.java index c50f98b45a1119..bdbf770f673832 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteral.java @@ -26,6 +26,7 @@ import org.apache.doris.nereids.types.DataType; import org.apache.doris.nereids.types.DateTimeType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.TimeV2Type; import org.apache.doris.nereids.types.coercion.DateLikeType; @@ -103,6 +104,7 @@ public DateTimeLiteral(DateLikeType dataType, long year, long month, long day, this.day = day; } + @Override public boolean isMidnight() { return hour == 0 && minute == 0 && second == 0 && microSecond == 0; } @@ -319,6 +321,16 @@ public long timePartToMicroSecond() { return ((hour * 60L + minute) * 60L + second) * 1000L * 1000L + microSecond; } + @Override + public long getTimePartInNanoseconds() { + return timePartToMicroSecond() * 1000L; + } + + @Override + public long getFractionalSecondInNanoseconds() { + return microSecond * 1000L; + } + @Override public double getDouble() { return (double) getValue(); @@ -408,6 +420,13 @@ protected Expression uncheckedCastTo(DataType targetType) throws AnalysisExcepti return new DateV2Literal(year, month, day); } else if (targetType.isDateType()) { return new DateLiteral(year, month, day); + } else if (targetType instanceof TimeStampNsType) { + try { + return new TimeStampNsLiteral(year, month, day, hour, minute, second, + microSecond * 1000); + } catch (AnalysisException e) { + throw new CastException(e.getMessage(), e); + } } else if (targetType.isDateTimeV2Type()) { // High scale datetime to low scale datetime may overflow. try { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeV2Literal.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeV2Literal.java index bfdf1e3be6eba5..6c812902f3753b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeV2Literal.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeV2Literal.java @@ -19,6 +19,7 @@ import org.apache.doris.analysis.LiteralExpr; import org.apache.doris.nereids.exceptions.AnalysisException; +import org.apache.doris.nereids.exceptions.CastException; import org.apache.doris.nereids.exceptions.NotSupportedException; import org.apache.doris.nereids.exceptions.UnboundException; import org.apache.doris.nereids.trees.expressions.Expression; @@ -27,6 +28,7 @@ import org.apache.doris.nereids.types.DataType; import org.apache.doris.nereids.types.DateTimeType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.qe.ConnectContext; @@ -67,10 +69,10 @@ public DateTimeV2Literal(DateTimeV2Type dateType, /** Date difference rounded toward zero by time part. */ public static long dateDiffInDaysRoundToZeroByTime(DateLiteral lhs, DateLiteral rhs) { long days = DateV2Literal.dateDiffInDays(lhs, rhs); - long microSecondDiff = timePartToMicroSecond(lhs) - timePartToMicroSecond(rhs); - if (days > 0 && microSecondDiff < 0) { + long nanosecondDiff = lhs.getTimePartInNanoseconds() - rhs.getTimePartInNanoseconds(); + if (days > 0 && nanosecondDiff < 0) { days--; - } else if (days < 0 && microSecondDiff > 0) { + } else if (days < 0 && nanosecondDiff > 0) { days++; } return days; @@ -88,10 +90,7 @@ public static long datetimeDiffInMicroSeconds(DateLiteral lhs, DateLiteral rhs) } private static long timePartToMicroSecond(DateLiteral date) { - if (date instanceof DateTimeLiteral) { - return ((DateTimeLiteral) date).timePartToMicroSecond(); - } - return 0; + return date.getTimePartInNanoseconds() / 1000L; } @Override @@ -199,6 +198,14 @@ protected Expression uncheckedCastTo(DataType targetType) throws AnalysisExcepti return new DateTimeLiteral((DateTimeType) targetType, year, month, day, hour, minute, second, microSecond); } + if (targetType instanceof TimeStampNsType) { + try { + return new TimeStampNsLiteral(year, month, day, hour, minute, second, + microSecond * 1000); + } catch (AnalysisException e) { + throw new CastException(e.getMessage(), e); + } + } if (targetType.isTimeStampTzType()) { DateTimeV2Literal dtV2Lit = (DateTimeV2Literal) (DateTimeExtractAndTransform.convertTz( this, @@ -421,6 +428,11 @@ public int getScale() { return ((DateTimeV2Type) dataType).getScale(); } + /** Return DATETIMEV2's microsecond fraction in the common nanosecond comparison unit. */ + public long getNanoSecond() { + return microSecond * 1000L; + } + public int commonScale(DateTimeV2Literal other) { return (int) Math.max(getScale(), other.getScale()); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java index 1c368179005be3..b252f30a86a60c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java @@ -335,11 +335,22 @@ public static Literal fromLegacyLiteral(LiteralExpr literalExpr, Type type) { } case DATETIMEV2: { org.apache.doris.analysis.DateLiteral dateLiteral = (org.apache.doris.analysis.DateLiteral) literalExpr; + DateTimeV2Type dateTimeV2Type = (DateTimeV2Type) DateType.fromCatalogType(type); + long fractionalSecond = dateLiteral.getMicrosecond(); return new DateTimeV2Literal( - (DateTimeV2Type) DateType.fromCatalogType(type), + dateTimeV2Type, dateLiteral.getYear(), dateLiteral.getMonth(), dateLiteral.getDay(), dateLiteral.getHour(), dateLiteral.getMinute(), dateLiteral.getSecond(), - dateLiteral.getMicrosecond() + fractionalSecond + ); + } + case TIMESTAMP_NS: { + org.apache.doris.analysis.TimeStampNsLiteral timestampNsLiteral + = (org.apache.doris.analysis.TimeStampNsLiteral) literalExpr; + return new TimeStampNsLiteral( + timestampNsLiteral.getYear(), timestampNsLiteral.getMonth(), timestampNsLiteral.getDay(), + timestampNsLiteral.getHour(), timestampNsLiteral.getMinute(), timestampNsLiteral.getSecond(), + timestampNsLiteral.getNanosecond() ); } case TIMESTAMPTZ: { @@ -628,7 +639,8 @@ private static Literal handleDateTimeLiteral(ByteBuffer data) { microsecond = data.getInt(); } if (Config.enable_date_conversion) { - return new DateTimeV2Literal(DateTimeV2Type.MAX, year, month, day, hour, minute, second, microsecond); + return new DateTimeV2Literal(DateTimeV2Type.MAX, + year, month, day, hour, minute, second, microsecond); } return new DateTimeLiteral(DateTimeType.INSTANCE, year, month, day, hour, minute, second, microsecond); } else { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/NumericLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/NumericLiteral.java index c871a7dc03cc7a..802721b15b36db 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/NumericLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/NumericLiteral.java @@ -25,6 +25,7 @@ import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateType; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import java.math.BigDecimal; @@ -154,21 +155,24 @@ protected String getDateTimeString(long value) { } protected Expression getDateLikeLiteral(String s, DataType targetType) { - DateTimeV2Literal l; + DateTimeV2Literal dateTime; try { - l = new DateTimeV2Literal(DateTimeV2Type.MAX, s); + dateTime = new DateTimeV2Literal(DateTimeV2Type.MAX, s); } catch (AnalysisException e) { throw new CastException(e.getMessage(), e); } if (targetType instanceof DateType) { - return new DateLiteral(l.getYear(), l.getMonth(), l.getDay()); + return new DateLiteral(dateTime.getYear(), dateTime.getMonth(), dateTime.getDay()); } if (targetType instanceof DateV2Type) { - return new DateV2Literal(l.getYear(), l.getMonth(), l.getDay()); + return new DateV2Literal(dateTime.getYear(), dateTime.getMonth(), dateTime.getDay()); } if (targetType instanceof DateTimeType) { return new DateTimeLiteral(s); } + if (targetType instanceof TimeStampNsType) { + return new TimeStampNsLiteral(s); + } if (targetType instanceof DateTimeV2Type) { return new DateTimeV2Literal((DateTimeV2Type) targetType, s); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StringLikeLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StringLikeLiteral.java index afe473ccf75ca7..68ec29f93f6721 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StringLikeLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StringLikeLiteral.java @@ -24,6 +24,7 @@ import org.apache.doris.nereids.trees.expressions.literal.format.DateTimeChecker; import org.apache.doris.nereids.types.DataType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.TimeV2Type; import org.apache.doris.qe.SessionVariable; @@ -144,9 +145,10 @@ protected Expression uncheckedCastTo(DataType targetType) throws AnalysisExcepti if (DateTimeChecker.hasTimeZone(value)) { return new TimestampTzLiteral(timeStampTzType, value); } - DateTimeV2Literal datetime = (DateTimeV2Literal) castToDateTime(DateTimeV2Type.MAX, strictCast); + DateTimeV2Literal datetime = (DateTimeV2Literal) castToDateTime( + DateTimeV2Type.MAX, strictCast); return TimestampTzLiteral.fromSessionTimeZone(timeStampTzType, datetime); - } else if (targetType.isDateTimeV2Type()) { + } else if (targetType.isTimeStampNsType() || targetType.isDateTimeV2Type()) { return castToDateTime(targetType, strictCast); } else if (targetType.isFloatType()) { return castToFloat(); @@ -379,6 +381,12 @@ protected DateLiteral getDateTimeLiteral(String year, String month, String date, } catch (AnalysisException e) { throw new CastException(e.getMessage(), e); } + } else if (targetType instanceof TimeStampNsType) { + try { + return new TimeStampNsLiteral(format); + } catch (AnalysisException e) { + throw new CastException(e.getMessage(), e); + } } else { try { return new DateTimeV2Literal((DateTimeV2Type) targetType, format); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/TimeStampNsLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/TimeStampNsLiteral.java new file mode 100644 index 00000000000000..471ffffdfae49e --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/TimeStampNsLiteral.java @@ -0,0 +1,348 @@ +// 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. + +package org.apache.doris.nereids.trees.expressions.literal; + +import org.apache.doris.analysis.LiteralExpr; +import org.apache.doris.nereids.exceptions.AnalysisException; +import org.apache.doris.nereids.exceptions.CastException; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DataType; +import org.apache.doris.nereids.types.DateTimeType; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.TimeV2Type; +import org.apache.doris.nereids.util.DateUtils; + +import java.math.BigInteger; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.temporal.ChronoField; +import java.time.temporal.TemporalAccessor; +import java.time.temporal.TemporalQueries; +import java.util.Objects; + +/** Literal for the fixed nanosecond-precision TIMESTAMP_NS type. */ +public final class TimeStampNsLiteral extends DateLiteral { + private static final long NANOS_PER_SECOND = 1_000_000_000L; + private static final long MAX_NANOSECOND = NANOS_PER_SECOND - 1; + private static final LocalDateTime MIN_VALUE + = LocalDateTime.of(1677, 9, 21, 0, 12, 43, 145224192); + private static final LocalDateTime MAX_VALUE + = LocalDateTime.of(2262, 4, 11, 23, 47, 16, 854775807); + + private final long hour; + private final long minute; + private final long second; + private final long nanosecond; + + public TimeStampNsLiteral(String value) { + this(parse(value)); + } + + /** Construct a TIMESTAMP_NS literal from civil datetime fields. */ + public TimeStampNsLiteral(long year, long month, long day, long hour, long minute, long second, + long nanosecond) { + super(TimeStampNsType.INSTANCE, year, month, day); + this.hour = hour; + this.minute = minute; + this.second = second; + this.nanosecond = nanosecond; + if (checkRange()) { + throw new AnalysisException("timestamp_ns literal [" + toString() + + "] is outside Int64 epoch nanosecond range"); + } + } + + private TimeStampNsLiteral(LocalDateTime value) { + this(value.getYear(), value.getMonthValue(), value.getDayOfMonth(), + value.getHour(), value.getMinute(), value.getSecond(), value.getNano()); + } + + private static LocalDateTime parse(String value) { + TemporalAccessor temporal = parseDateTime(value, DateUtils.NANOSECOND_SCALE + 1).get(); + long year = DateUtils.getOrDefault(temporal, ChronoField.YEAR); + long month = DateUtils.getOrDefault(temporal, ChronoField.MONTH_OF_YEAR); + long day = DateUtils.getOrDefault(temporal, ChronoField.DAY_OF_MONTH); + long hour = DateUtils.getOrDefault(temporal, ChronoField.HOUR_OF_DAY); + long minute = DateUtils.getOrDefault(temporal, ChronoField.MINUTE_OF_HOUR); + long second = DateUtils.getOrDefault(temporal, ChronoField.SECOND_OF_MINUTE); + + ZoneId zoneId = temporal.query(TemporalQueries.zone()); + if (zoneId != null) { + LocalDateTime converted = DateUtils.convertTimeZone( + year, month, day, hour, minute, second, zoneId, DateUtils.getTimeZone()); + year = converted.getYear(); + month = converted.getMonthValue(); + day = converted.getDayOfMonth(); + hour = converted.getHour(); + minute = converted.getMinute(); + second = converted.getSecond(); + } + + LocalDateTime result = LocalDateTime.of((int) year, (int) month, (int) day, + (int) hour, (int) minute, (int) second, + DateUtils.getOrDefault(temporal, ChronoField.NANO_OF_SECOND)); + if (DateUtils.getNanosecondGuardDigit(value) >= 5) { + result = result.plusNanos(1); + } + return result; + } + + public static TimeStampNsLiteral getMinValue() { + return new TimeStampNsLiteral(MIN_VALUE); + } + + public static TimeStampNsLiteral getMaxValue() { + return new TimeStampNsLiteral(MAX_VALUE); + } + + public static TimeStampNsLiteral createEndOfDay(long year, long month, long day) { + return new TimeStampNsLiteral(year, month, day, 23, 59, 59, MAX_NANOSECOND); + } + + public static TimeStampNsLiteral fromJavaDateType(LocalDateTime dateTime) { + return new TimeStampNsLiteral(dateTime); + } + + /** Return whether the civil fields are invalid or outside the signed epoch-nanosecond range. */ + public boolean checkRange() { + if (checkRange(year, month, day) || month < 1 || day < 1 || checkDate(year, month, day) + || hour < 0 || hour > 23 || minute < 0 || minute > 59 + || second < 0 || second > 59 || nanosecond < 0 || nanosecond > MAX_NANOSECOND) { + return true; + } + LocalDateTime value = toJavaDateType(); + return value.isBefore(MIN_VALUE) || value.isAfter(MAX_VALUE); + } + + @Override + public boolean isMidnight() { + return hour == 0 && minute == 0 && second == 0 && nanosecond == 0; + } + + @Override + public TimeStampNsType getDataType() { + return TimeStampNsType.INSTANCE; + } + + @Override + public Long getValue() { + return (year * 10000 + month * 100 + day) * 1000000L + hour * 10000 + minute * 100 + second; + } + + @Override + public long getTimePartInNanoseconds() { + return ((hour * 60L + minute) * 60L + second) * NANOS_PER_SECOND + nanosecond; + } + + @Override + public long getFractionalSecondInNanoseconds() { + return nanosecond; + } + + @Override + public double getDouble() { + return getValue() + nanosecond / (double) NANOS_PER_SECOND; + } + + @Override + public String getStringValue() { + return DateUtils.formatDateTime(year, month, day, hour, minute, second, + nanosecond, TimeStampNsType.SCALE); + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitTimeStampNsLiteral(this, context); + } + + @Override + public LiteralExpr toLegacyLiteral() { + return new org.apache.doris.analysis.TimeStampNsLiteral( + year, month, day, hour, minute, second, nanosecond); + } + + public DateTimeV2Literal roundFloorToDateTimeV2(int scale) { + long factor = (long) Math.pow(10, DateUtils.NANOSECOND_SCALE - scale); + LocalDateTime rounded = toJavaDateType().withNano((int) (nanosecond / factor * factor)); + return DateTimeV2Literal.fromJavaDateType(rounded, scale); + } + + public DateTimeV2Literal roundCeilingToDateTimeV2(int scale) { + long factor = (long) Math.pow(10, DateUtils.NANOSECOND_SCALE - scale); + long remainder = nanosecond % factor; + LocalDateTime rounded = remainder == 0 ? toJavaDateType() + : toJavaDateType().plusNanos(factor - remainder); + return DateTimeV2Literal.fromJavaDateType(rounded, scale); + } + + @Override + public LocalDateTime toJavaDateType() { + return LocalDateTime.of((int) year, (int) month, (int) day, + (int) hour, (int) minute, (int) second, (int) nanosecond); + } + + @Override + public TimeStampNsLiteral plusDays(long days) { + return fromJavaDateType(toJavaDateType().plusDays(days)); + } + + @Override + public TimeStampNsLiteral plusMonths(long months) { + return fromJavaDateType(toJavaDateType().plusMonths(months)); + } + + @Override + public TimeStampNsLiteral plusWeeks(long weeks) { + return fromJavaDateType(toJavaDateType().plusWeeks(weeks)); + } + + @Override + public TimeStampNsLiteral plusYears(long years) { + return fromJavaDateType(toJavaDateType().plusYears(years)); + } + + public TimeStampNsLiteral plusHours(long hours) { + return fromJavaDateType(toJavaDateType().plusHours(hours)); + } + + public TimeStampNsLiteral plusMinutes(long minutes) { + return fromJavaDateType(toJavaDateType().plusMinutes(minutes)); + } + + public TimeStampNsLiteral plusSeconds(long seconds) { + return fromJavaDateType(toJavaDateType().plusSeconds(seconds)); + } + + public TimeStampNsLiteral plusMicroSeconds(long microSeconds) { + return fromJavaDateType(toJavaDateType().plusNanos(Math.multiplyExact(microSeconds, 1000L))); + } + + public TimeStampNsLiteral plusMilliSeconds(long milliSeconds) { + return plusMicroSeconds(Math.multiplyExact(milliSeconds, 1000L)); + } + + public long getHour() { + return hour; + } + + public long getMinute() { + return minute; + } + + public long getSecond() { + return second; + } + + public long getMicroSecond() { + return nanosecond / 1000; + } + + public long getNanoSecond() { + return nanosecond; + } + + public int getScale() { + return TimeStampNsType.SCALE; + } + + @Override + protected Expression uncheckedCastTo(DataType targetType) throws AnalysisException { + if (getDataType().equals(targetType)) { + return this; + } + if (targetType.isBigIntType()) { + return new BigIntLiteral(getValue()); + } + if (targetType.isLargeIntType()) { + return new LargeIntLiteral(new BigInteger(String.valueOf(getValue()))); + } + if (targetType.isDateType()) { + return new DateLiteral(year, month, day); + } + if (targetType.isDateV2Type()) { + return new DateV2Literal(year, month, day); + } + if (targetType.isDateTimeType()) { + return new DateTimeLiteral((DateTimeType) targetType, + year, month, day, hour, minute, second, 0); + } + if (targetType instanceof DateTimeV2Type) { + DateTimeV2Type dateTimeV2Type = (DateTimeV2Type) targetType; + LocalDateTime rounded = roundToScale(dateTimeV2Type.getScale()); + return DateTimeV2Literal.fromJavaDateType(rounded, dateTimeV2Type.getScale()); + } + if (targetType.isTimeType()) { + int scale = ((TimeV2Type) targetType).getScale(); + long factor = (long) Math.pow(10, DateUtils.NANOSECOND_SCALE - scale); + long timeNanos = getTimePartInNanoseconds() + factor / 2; + int resultHour = (int) (timeNanos / NANOS_PER_SECOND / 60 / 60); + int resultMinute = (int) (timeNanos / NANOS_PER_SECOND / 60 % 60); + int resultSecond = (int) (timeNanos / NANOS_PER_SECOND % 60); + int resultMicroSecond = (int) (timeNanos % NANOS_PER_SECOND / 1000 / (factor / 1000) + * (factor / 1000)); + return new TimeV2Literal(resultHour, resultMinute, resultSecond, + resultMicroSecond, scale, false); + } + if (targetType.isTimeStampTzType()) { + int scale = ((TimeStampTzType) targetType).getScale(); + LocalDateTime rounded = roundToScale(scale); + DateTimeV2Literal local = DateTimeV2Literal.fromJavaDateType(rounded, scale); + return local.checkedCastTo(targetType); + } + if (targetType.isFloatType()) { + return new FloatLiteral(getValue()); + } + if (targetType.isDoubleType()) { + return new DoubleLiteral(getValue()); + } + if (targetType.isIntegralType()) { + throw new CastException(getStringValue() + " can't cast to " + targetType.toSql()); + } + try { + return super.uncheckedCastTo(targetType); + } catch (AnalysisException e) { + throw new CastException(e.getMessage(), e); + } + } + + private LocalDateTime roundToScale(int scale) { + long factor = (long) Math.pow(10, DateUtils.NANOSECOND_SCALE - scale); + LocalDateTime rounded = toJavaDateType().plusNanos(factor / 2); + return rounded.withNano((int) (rounded.getNano() / factor * factor)); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof TimeStampNsLiteral)) { + return false; + } + TimeStampNsLiteral literal = (TimeStampNsLiteral) o; + return Objects.equals(getValue(), literal.getValue()) && nanosecond == literal.nanosecond; + } + + @Override + protected int computeHashCode() { + return Objects.hash(getValue(), nanosecond); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/TimeV2Literal.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/TimeV2Literal.java index 8d04a006baf51a..b400b5b4919b8c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/TimeV2Literal.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/TimeV2Literal.java @@ -22,6 +22,7 @@ import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DataType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeV2Type; import org.apache.doris.nereids.util.DateUtils; @@ -314,6 +315,9 @@ protected Expression uncheckedCastTo(DataType targetType) throws AnalysisExcepti } else if (targetType.isDateTimeType()) { return new DateTimeLiteral(time.getYear(), time.getMonth(), time.getDay(), time.getHour(), time.getMinute(), time.getSecond()); + } else if (targetType instanceof TimeStampNsType) { + return new TimeStampNsLiteral(time.getYear(), time.getMonth(), time.getDay(), + time.getHour(), time.getMinute(), time.getSecond(), time.getMicroSecond() * 1000L); } else if (targetType.isDateTimeV2Type()) { return time; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/TimestampTzLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/TimestampTzLiteral.java index 810168d4985a51..cca1919f5d3f3a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/TimestampTzLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/TimestampTzLiteral.java @@ -27,6 +27,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DataType; import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.qe.ConnectContext; @@ -170,6 +171,15 @@ protected Expression uncheckedCastTo(DataType targetType) throws AnalysisExcepti if (targetType.isTimeStampTzType()) { return new TimestampTzLiteral((TimeStampTzType) targetType, year, month, day, hour, minute, second, microSecond); + } else if (targetType instanceof TimeStampNsType) { + DateTimeV2Literal dtV2Lit = new DateTimeV2Literal(DateTimeV2Type.MAX, + year, month, day, hour, minute, second, microSecond); + dtV2Lit = (DateTimeV2Literal) DateTimeExtractAndTransform.convertTz( + dtV2Lit, new StringLiteral("UTC"), + new StringLiteral(ConnectContext.get().getSessionVariable().timeZone)); + return new TimeStampNsLiteral(dtV2Lit.getYear(), dtV2Lit.getMonth(), dtV2Lit.getDay(), + dtV2Lit.getHour(), dtV2Lit.getMinute(), dtV2Lit.getSecond(), + dtV2Lit.getMicroSecond() * 1000L); } else if (targetType.isDateTimeV2Type()) { DateTimeV2Literal dtV2Lit = new DateTimeV2Literal((DateTimeV2Type) targetType, year, month, day, hour, minute, second, microSecond); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ExpressionVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ExpressionVisitor.java index a25b110dfb438a..acf4d0a35711d9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ExpressionVisitor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ExpressionVisitor.java @@ -120,6 +120,7 @@ import org.apache.doris.nereids.trees.expressions.literal.SmallIntLiteral; import org.apache.doris.nereids.trees.expressions.literal.StringLiteral; import org.apache.doris.nereids.trees.expressions.literal.StructLiteral; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.trees.expressions.literal.TimeV2Literal; import org.apache.doris.nereids.trees.expressions.literal.TimestampTzLiteral; import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral; @@ -337,6 +338,10 @@ public R visitDateTimeV2Literal(DateTimeV2Literal dateTimeV2Literal, C context) return visitLiteral(dateTimeV2Literal, context); } + public R visitTimeStampNsLiteral(TimeStampNsLiteral timeStampNsLiteral, C context) { + return visitLiteral(timeStampNsLiteral, context); + } + public R visitTimestampTzLiteral(TimestampTzLiteral timestampTzLiteral, C context) { return visitLiteral(timestampTzLiteral, context); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreateFunctionCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreateFunctionCommand.java index 0cdb1be3c5dcbe..0dbd2c2d954f81 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreateFunctionCommand.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreateFunctionCommand.java @@ -1047,6 +1047,9 @@ private Types.PGenericType convertToPParameterType(Type arg) throws AnalysisExce case TIMEV2: typeBuilder.setId(Types.PGenericType.TypeId.DATETIMEV2); break; + case TIMESTAMP_NS: + typeBuilder.setId(Types.PGenericType.TypeId.TIMESTAMP_NS); + break; case TIMESTAMPTZ: typeBuilder.setId(Types.PGenericType.TypeId.TIMESTAMPTZ); break; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/DefaultValue.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/DefaultValue.java index ad5f41ec2d1816..e33c9f89b80daa 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/DefaultValue.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/DefaultValue.java @@ -18,9 +18,11 @@ package org.apache.doris.nereids.trees.plans.commands.info; import org.apache.doris.analysis.DefaultValueExprDef; -import org.apache.doris.catalog.ScalarType; import org.apache.doris.common.util.TimeUtils; import org.apache.doris.nereids.exceptions.AnalysisException; +import org.apache.doris.nereids.types.DataType; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -81,9 +83,17 @@ public DefaultValue(String value, String exprName, Long precision) { * default value current_timestamp(precision) */ public static DefaultValue currentTimeStampDefaultValueWithPrecision(Long precision) { - if (precision > ScalarType.MAX_DATETIMEV2_SCALE || precision < 0) { + return currentTimeStampDefaultValueWithPrecision(precision, DateTimeV2Type.SYSTEM_DEFAULT); + } + + /** + * default value current_timestamp(precision), validated against the target column type + */ + public static DefaultValue currentTimeStampDefaultValueWithPrecision(Long precision, DataType type) { + int maxScale = type.isTimeStampNsType() ? TimeStampNsType.SCALE : DateTimeV2Type.MAX_SCALE; + if (precision > maxScale || precision < 0) { throw new AnalysisException("column's default value current_timestamp" - + " precision must be between 0 and 6"); + + " precision must be between 0 and " + maxScale); } if (precision == 0) { return new DefaultValue(CURRENT_TIMESTAMP, NOW); @@ -118,22 +128,10 @@ public String getRawValue() { return LocalDateTime.now(TimeUtils.getTimeZone().toZoneId()).toString().replace('T', ' '); } else if (isCurrentTimeStampWithPrecision()) { long precision = getCurrentTimeStampPrecision(); - String format = "yyyy-MM-dd HH:mm:ss"; if (precision == 0) { return LocalDateTime.now(TimeUtils.getTimeZone().toZoneId()).toString().replace('T', ' '); - } else if (precision == 1) { - format = "yyyy-MM-dd HH:mm:ss.S"; - } else if (precision == 2) { - format = "yyyy-MM-dd HH:mm:ss.SS"; - } else if (precision == 3) { - format = "yyyy-MM-dd HH:mm:ss.SSS"; - } else if (precision == 4) { - format = "yyyy-MM-dd HH:mm:ss.SSSS"; - } else if (precision == 5) { - format = "yyyy-MM-dd HH:mm:ss.SSSSS"; - } else if (precision == 6) { - format = "yyyy-MM-dd HH:mm:ss.SSSSSS"; } + String format = "yyyy-MM-dd HH:mm:ss." + "S".repeat((int) precision); return LocalDateTime.now(TimeUtils.getTimeZone().toZoneId()) .format(DateTimeFormatter.ofPattern(format)); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertUtils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertUtils.java index aee5f6565fb256..c777b75dcac7ef 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertUtils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertUtils.java @@ -58,6 +58,7 @@ import org.apache.doris.nereids.trees.expressions.NamedExpression; import org.apache.doris.nereids.trees.expressions.literal.Literal; import org.apache.doris.nereids.trees.expressions.literal.NullLiteral; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.algebra.InlineTable; import org.apache.doris.nereids.trees.plans.commands.info.DMLCommandType; @@ -68,6 +69,7 @@ import org.apache.doris.nereids.types.DataType; import org.apache.doris.nereids.types.VarcharType; import org.apache.doris.nereids.util.RelationUtil; +import org.apache.doris.nereids.util.TimestampNsDefaultValueUtils; import org.apache.doris.nereids.util.TypeCoercionUtils; import org.apache.doris.proto.InternalService; import org.apache.doris.qe.ConnectContext; @@ -668,6 +670,11 @@ static NamedExpression generateDefaultExpression(Column column) { if (generatedColumnInfo != null) { return new Alias(new NullLiteral(DataType.fromCatalogType(column.getType())), column.getName()); } + Optional timestampNsDefault + = TimestampNsDefaultValueUtils.currentTimestampLiteral(column); + if (timestampNsDefault.isPresent()) { + return new Alias(timestampNsDefault.get(), column.getName()); + } String defaultValueSql = column.getDefaultValueSql(); if (defaultValueSql == null) { if (!column.isAllowNull() && !column.isAutoInc()) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java index c6a5dc1b0285ad..db00b4cc6e55e0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java @@ -77,6 +77,7 @@ private static Map initMap() { .put(Type.DATEV2.getPrimitiveType(), DateType.INSTANCE) .put(Type.DATETIME.getPrimitiveType(), DateTimeType.INSTANCE) .put(Type.DATETIMEV2.getPrimitiveType(), DateTimeV2Type.SYSTEM_DEFAULT) + .put(Type.TIMESTAMP_NS.getPrimitiveType(), TimeStampNsType.INSTANCE) .put(Type.TIMESTAMPTZ.getPrimitiveType(), TimeStampTzType.SYSTEM_DEFAULT) .put(Type.DECIMALV2.getPrimitiveType(), DecimalV2Type.SYSTEM_DEFAULT) .put(Type.DECIMAL32.getPrimitiveType(), DecimalV3Type.SYSTEM_DEFAULT) @@ -118,7 +119,8 @@ private static Map initMap() { .add(DateType.class, () -> ImmutableList.of( DateTimeType.INSTANCE, DateV2Type.INSTANCE, StringType.INSTANCE)) .add(DateV2Type.class, () -> ImmutableList.of(DateTimeV2Type.SYSTEM_DEFAULT, StringType.INSTANCE)) - .add(TimeV2Type.class, () -> ImmutableList.of(DateTimeV2Type.MAX, StringType.INSTANCE)) + .add(TimeV2Type.class, () -> ImmutableList.of( + DateTimeV2Type.MAX, StringType.INSTANCE)) .build(); public static Map legacyTypeToNereidsType() { @@ -351,6 +353,12 @@ public static DataType convertPrimitiveFromStrings(List types) { throw new AnalysisException("Nereids do not support type: " + type); } break; + case "timestamp_ns": + if (types.size() != 1) { + throw new AnalysisException("timestamp_ns does not support precision"); + } + dataType = TimeStampNsType.INSTANCE; + break; case "timestamptz": switch (types.size()) { case 1: @@ -424,6 +432,7 @@ public static DataType fromCatalogType(Type type) { case DOUBLE: return DoubleType.INSTANCE; case NULL_TYPE: return NullType.INSTANCE; case DATETIMEV2: return DateTimeV2Type.of(((ScalarType) type).getScalarScale()); + case TIMESTAMP_NS: return TimeStampNsType.INSTANCE; case DATETIME: return DateTimeType.INSTANCE; case DATEV2: return DateV2Type.INSTANCE; case DATE: return DateType.INSTANCE; @@ -623,7 +632,8 @@ public boolean isDateType() { } public boolean isDateLikeType() { - return isDateType() || isDateTimeType() || isDateV2Type() || isDateTimeV2Type() || isTimeStampTzType(); + return isDateType() || isDateTimeType() || isDateV2Type() || isDateTimeV2Type() + || isTimeStampNsType() || isTimeStampTzType(); } public boolean isTimeType() { @@ -634,6 +644,10 @@ public boolean isTimeStampTzType() { return this instanceof TimeStampTzType; } + public boolean isTimeStampNsType() { + return this instanceof TimeStampNsType; + } + public boolean isNullType() { return this instanceof NullType; } @@ -1097,20 +1111,35 @@ private static void validateScalarType(ScalarType scalarType) { + precision + " in not supported."); } } + case TIMESTAMP_NS: + // TIMESTAMP_NS has fixed nanosecond precision and carries no variable precision/scale metadata. + break; + case DATETIMEV2: { + int precision = scalarType.decimalPrecision(); + int scale = scalarType.decimalScale(); + if (precision != ScalarType.DATETIME_PRECISION) { + throw new AnalysisException( + "Precision of Datetime must be " + ScalarType.DATETIME_PRECISION + + "." + " Precision was set to: " + precision + "."); + } + if (scale < 0 || scale > ScalarType.MAX_DATETIMEV2_SCALE) { + throw new AnalysisException("Scale of Datetime must between 0 and " + + ScalarType.MAX_DATETIMEV2_SCALE + "." + + " Scale was set to: " + scale + "."); + } + break; + } case TIMEV2: - case DATETIMEV2: case TIMESTAMPTZ: { int precision = scalarType.decimalPrecision(); int scale = scalarType.decimalScale(); - // precision: 18 if (precision != ScalarType.DATETIME_PRECISION) { throw new AnalysisException( - "Precision of Datetime/Time must be " + ScalarType.DATETIME_PRECISION + "Precision of Time must be " + ScalarType.DATETIME_PRECISION + "." + " Precision was set to: " + precision + "."); } - // scale: [0, 6] if (scale < 0 || scale > 6) { - throw new AnalysisException("Scale of Datetime/Time must between 0 and 6." + throw new AnalysisException("Scale of Time must between 0 and 6." + " Scale was set to: " + scale + "."); } break; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/TimeStampNsType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/TimeStampNsType.java new file mode 100644 index 00000000000000..d194fecd311461 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/TimeStampNsType.java @@ -0,0 +1,99 @@ +// 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. + +package org.apache.doris.nereids.types; + +import org.apache.doris.catalog.ScalarType; +import org.apache.doris.catalog.Type; +import org.apache.doris.nereids.trees.expressions.literal.StringLikeLiteral; +import org.apache.doris.nereids.types.coercion.CharacterType; +import org.apache.doris.nereids.types.coercion.DateLikeType; +import org.apache.doris.nereids.types.coercion.ScaleTimeType; + +import java.time.DateTimeException; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; + +/** + * Timestamp represented as signed nanoseconds since the Unix epoch. + * + *

TIMESTAMP_NS is date-like and has a fixed scale, but it is not a DATETIMEV2 precision variant: + * the two types have different physical representations and coercion rules. Keeping it directly under + * {@link DateLikeType} prevents generic DATETIMEV2 code from treating its fixed nanosecond scale as a + * DATETIMEV2 scale.

+ */ +public final class TimeStampNsType extends DateLikeType implements ScaleTimeType { + public static final int SCALE = ScalarType.TIMESTAMP_NS_SCALE; + public static final TimeStampNsType INSTANCE = new TimeStampNsType(); + + private static final int WIDTH = 8; + + private TimeStampNsType() { + } + + @Override + public boolean isInjectiveCastTo(DataType target) { + return target instanceof TimeStampNsType || target instanceof CharacterType; + } + + @Override + public Type toCatalogDataType() { + return ScalarType.createTimeStampNsType(); + } + + @Override + public ScaleTimeType scaleTypeForType(DataType dataType) { + return INSTANCE; + } + + @Override + public ScaleTimeType forTypeFromString(StringLikeLiteral str) { + return INSTANCE; + } + + @Override + public int getScale() { + return SCALE; + } + + @Override + public int width() { + return WIDTH; + } + + @Override + public double rangeLength(double high, double low) { + if (high == low) { + return 0; + } + if (Double.isInfinite(high) || Double.isInfinite(low)) { + return Double.POSITIVE_INFINITY; + } + try { + LocalDateTime to = toLocalDateTime(high); + LocalDateTime from = toLocalDateTime(low); + return ChronoUnit.SECONDS.between(from, to); + } catch (DateTimeException e) { + return Double.POSITIVE_INFINITY; + } + } + + @Override + public String toSql() { + return "timestamp_ns"; + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/coercion/DateLikeType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/coercion/DateLikeType.java index 1f8130215b04e2..f931ff2ce27c10 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/coercion/DateLikeType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/coercion/DateLikeType.java @@ -22,10 +22,12 @@ import org.apache.doris.nereids.trees.expressions.literal.DateTimeLiteral; import org.apache.doris.nereids.trees.expressions.literal.DateTimeV2Literal; import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.types.DateTimeType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateType; import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; import java.time.LocalDate; import java.time.LocalDateTime; @@ -70,6 +72,8 @@ public DateLiteral fromString(String s) { return new DateV2Literal(l.getYear(), l.getMonth(), l.getDay()); } else if (this instanceof DateTimeType) { return new DateTimeLiteral(s); + } else if (this instanceof TimeStampNsType) { + return new TimeStampNsLiteral(s); } else if (this instanceof DateTimeV2Type) { return new DateTimeV2Literal((DateTimeV2Type) this, s); } else { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateTimeFormatterUtils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateTimeFormatterUtils.java index e8ff854945a0a2..dc1536f2a745a6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateTimeFormatterUtils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateTimeFormatterUtils.java @@ -18,10 +18,12 @@ package org.apache.doris.nereids.util; import org.apache.doris.nereids.exceptions.AnalysisException; -import org.apache.doris.nereids.trees.expressions.literal.DateTimeV2Literal; +import org.apache.doris.nereids.trees.expressions.literal.DateLiteral; import org.apache.doris.nereids.trees.expressions.literal.StringLikeLiteral; import org.apache.doris.nereids.trees.expressions.literal.TimeV2Literal; +import org.apache.doris.nereids.types.TimeStampNsType; +import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.format.ResolverStyle; @@ -56,14 +58,13 @@ public class DateTimeFormatterUtils { .appendLiteral('-').appendValue(ChronoField.MONTH_OF_YEAR, 2) .appendLiteral('-').appendValue(ChronoField.DAY_OF_MONTH, 2) .toFormatter().withResolverStyle(ResolverStyle.STRICT); - // HH[:mm][:ss][.microsecond] + // HH[:mm][:ss][.fraction] public static final DateTimeFormatter TIME_FORMATTER = new DateTimeFormatterBuilder() .appendValue(ChronoField.HOUR_OF_DAY, 2) .appendLiteral(':').appendValue(ChronoField.MINUTE_OF_HOUR, 2) .appendLiteral(':').appendValue(ChronoField.SECOND_OF_MINUTE, 2) - // microsecond maxWidth is 7, we may need 7th digit to judge overflow .appendOptional(new DateTimeFormatterBuilder() - .appendFraction(ChronoField.NANO_OF_SECOND, 1, 7, true).toFormatter()) + .appendFraction(ChronoField.NANO_OF_SECOND, 1, TimeStampNsType.SCALE, true).toFormatter()) .toFormatter().withResolverStyle(ResolverStyle.STRICT); // Time without delimiter: HHmmss[.microsecond] private static final DateTimeFormatter BASIC_TIME_FORMATTER = new DateTimeFormatterBuilder() @@ -71,7 +72,7 @@ public class DateTimeFormatterUtils { .appendValue(ChronoField.MINUTE_OF_HOUR, 2) .appendValue(ChronoField.SECOND_OF_MINUTE, 2) .appendOptional(new DateTimeFormatterBuilder() - .appendFraction(ChronoField.NANO_OF_SECOND, 1, 7, true).toFormatter()) + .appendFraction(ChronoField.NANO_OF_SECOND, 1, TimeStampNsType.SCALE, true).toFormatter()) .toFormatter().withResolverStyle(ResolverStyle.STRICT); // yyyymmdd private static final DateTimeFormatter BASIC_DATE_FORMATTER = new DateTimeFormatterBuilder() @@ -150,15 +151,16 @@ private static void appendTwoDigits(StringBuilder builder, int value) { * @param isTimeFormat true when invoked via time_format, false for date_format * @return formatted string or null when pattern requires missing date fields */ - public static String toFormatStringConservative(DateTimeV2Literal datetime, StringLikeLiteral format, + public static String toFormatStringConservative(DateLiteral datetime, StringLikeLiteral format, boolean isTimeFormat) { - int year = isTimeFormat ? 0 : (int) datetime.getYear(); - int month = isTimeFormat ? 0 : (int) datetime.getMonth(); - int day = isTimeFormat ? 0 : (int) datetime.getDay(); - int hour = (int) datetime.getHour(); - int minute = (int) datetime.getMinute(); - int second = (int) datetime.getSecond(); - int microsecond = (int) datetime.getMicroSecond(); + LocalDateTime dateTime = datetime.toJavaDateType(); + int year = isTimeFormat ? 0 : dateTime.getYear(); + int month = isTimeFormat ? 0 : dateTime.getMonthValue(); + int day = isTimeFormat ? 0 : dateTime.getDayOfMonth(); + int hour = dateTime.getHour(); + int minute = dateTime.getMinute(); + int second = dateTime.getSecond(); + int microsecond = dateTime.getNano() / 1000; String pattern = trimFormat(format.getValue()); return formatTemporalLiteral(year, month, day, hour, minute, second, microsecond, pattern); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateUtils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateUtils.java index e339471e447fb9..685819c481d579 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateUtils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateUtils.java @@ -27,6 +27,7 @@ import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; +import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.format.ResolverStyle; @@ -37,6 +38,9 @@ import java.time.temporal.TemporalAccessor; import java.time.temporal.WeekFields; import java.time.zone.ZoneOffsetTransition; +import java.time.zone.ZoneRules; +import java.util.Arrays; +import java.util.List; import java.util.Locale; import java.util.Set; @@ -44,6 +48,7 @@ * date util tools. */ public class DateUtils { + public static final int NANOSECOND_SCALE = 9; public static final Set monoFormat = ImmutableSet.of("yyyyMMdd", "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "%Y", "%Y-%m", "%Y-%m-%d", "%Y-%m-%d %H", "%Y-%m-%d %H:%i", "%Y-%m-%d %H:%i:%s", "%Y-%m-%d %H:%i:%S", "%Y-%m-%d %T", "%Y%m%d", "%Y%m"); @@ -389,6 +394,98 @@ public static int getOrDefault(final TemporalAccessor accessor, final ChronoFiel return accessor.isSupported(field) ? accessor.get(field) : /* default value */ 0; } + /** + * Remove the TIMESTAMP_NS rounding guard digit before parsing because Java accepts at most + * nine fractional-second digits. The guard remains available in the original string and can + * be retrieved by {@link #getNanosecondGuardDigit(String)} during target-scale rounding. + */ + public static String truncateFractionalSecondForJavaParser(String s) { + int dot = s.lastIndexOf('.'); + if (dot < 0) { + return s; + } + int fractionEnd = dot + 1; + while (fractionEnd < s.length() && Character.isDigit(s.charAt(fractionEnd))) { + fractionEnd++; + } + int retainedEnd = Math.min(dot + NANOSECOND_SCALE + 1, fractionEnd); + return retainedEnd == fractionEnd ? s : s.substring(0, retainedEnd) + s.substring(fractionEnd); + } + + /** Return the TIMESTAMP_NS rounding guard digit, or -1 when the input has none. */ + public static int getNanosecondGuardDigit(String s) { + int dot = s.lastIndexOf('.'); + int guardIndex = dot + NANOSECOND_SCALE + 1; + if (dot < 0 || guardIndex >= s.length() || !Character.isDigit(s.charAt(guardIndex))) { + return -1; + } + return s.charAt(guardIndex) - '0'; + } + + /** Format a datetime with the requested number of fractional-second digits. */ + public static String formatDateTime(long year, long month, long day, long hour, long minute, + long second, long nanosecond, int scale) { + if (0 <= year && year <= 9999 && 0 <= month && month <= 99 && 0 <= day && day <= 99 + && 0 <= hour && hour <= 99 && 0 <= minute && minute <= 99 + && 0 <= second && second <= 99 && 0 <= nanosecond && nanosecond < 1_000_000_000L) { + int length = scale == 0 ? 19 : 20 + scale; + char[] value = new char[length]; + Arrays.fill(value, '0'); + value[4] = '-'; + value[7] = '-'; + value[10] = ' '; + value[13] = ':'; + value[16] = ':'; + fillPaddedValue(value, 0, year, 4); + fillPaddedValue(value, 5, month, 2); + fillPaddedValue(value, 8, day, 2); + fillPaddedValue(value, 11, hour, 2); + fillPaddedValue(value, 14, minute, 2); + fillPaddedValue(value, 17, second, 2); + if (scale > 0) { + value[19] = '.'; + long divisor = (long) Math.pow(10, NANOSECOND_SCALE - scale); + fillPaddedValue(value, 20, nanosecond / divisor, scale); + } + return String.valueOf(value); + } + String fractionFormat = scale > 0 ? ".%0" + scale + "d" : ""; + long divisor = (long) Math.pow(10, NANOSECOND_SCALE - scale); + return String.format("%04d-%02d-%02d %02d:%02d:%02d" + fractionFormat, + year, month, day, hour, minute, second, nanosecond / divisor); + } + + private static void fillPaddedValue(char[] buffer, int start, long value, int length) { + for (int i = start + length - 1; i >= start; i--) { + buffer[i] = (char) ('0' + value % 10); + value /= 10; + } + } + + /** Convert a civil datetime between time zones using the same DST policy as BE cctz. */ + public static LocalDateTime convertTimeZone(long year, long month, long day, long hour, long minute, + long second, ZoneId fromZone, ZoneId toZone) { + LocalDateTime localDateTime = LocalDateTime.of((int) year, (int) month, (int) day, + (int) hour, (int) minute, (int) second); + return LocalDateTime.ofInstant(convertLocalToInstant(localDateTime, fromZone), toZone); + } + + /** + * Convert a local civil datetime to an instant with the same overlap/gap policy as BE cctz. + * Repeated local times use the pre-transition offset; skipped local times map to the transition + * instant. + */ + public static Instant convertLocalToInstant(LocalDateTime localDateTime, ZoneId fromZone) { + ZoneRules rules = fromZone.getRules(); + List validOffsets = rules.getValidOffsets(localDateTime); + int size = validOffsets.size(); + if (size == 1 || size == 2) { + return localDateTime.atOffset(validOffsets.get(0)).toInstant(); + } + ZoneOffsetTransition transition = rules.getTransition(localDateTime); + return transition.getInstant(); + } + /** * get hour from accessor, if not support hour field, return 0 */ diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/PredicateInferUtils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/PredicateInferUtils.java index 5e0fc4fb7fbde7..d6f7dfc145c732 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/PredicateInferUtils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/PredicateInferUtils.java @@ -146,10 +146,16 @@ private static Optional validForInfer(Expression expression, InferTy return validForInfer(child, inferType); } } else if (dataType instanceof DateTimeType) { + if (childType.isTimeStampNsType()) { + return Optional.empty(); + } if (!(childType instanceof DateTimeV2Type)) { return validForInfer(child, inferType); } } else if (dataType instanceof DateTimeV2Type) { + if (childType.isTimeStampNsType()) { + return Optional.empty(); + } return validForInfer(child, inferType); } } else if (inferType == InferType.STRING) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TimestampNsDefaultValueUtils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TimestampNsDefaultValueUtils.java new file mode 100644 index 00000000000000..04def0fbf5a873 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TimestampNsDefaultValueUtils.java @@ -0,0 +1,58 @@ +// 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. + +package org.apache.doris.nereids.util; + +import org.apache.doris.analysis.ColumnDef; +import org.apache.doris.analysis.DefaultValueExprDef; +import org.apache.doris.catalog.Column; +import org.apache.doris.common.util.TimeUtils; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampNsType; + +import java.time.LocalDateTime; +import java.util.Optional; + +/** Utilities for expanding TIMESTAMP_NS default expressions. */ +public final class TimestampNsDefaultValueUtils { + + private TimestampNsDefaultValueUtils() { + } + + /** + * Expand CURRENT_TIMESTAMP precision that DATETIMEV2 cannot represent into a TIMESTAMP_NS literal. + * The normal function path is retained for precision 0 through 6. + */ + public static Optional currentTimestampLiteral(Column column) { + if (!column.getType().isTimeStampNs()) { + return Optional.empty(); + } + DefaultValueExprDef expression = column.getDefaultValueExprDef(); + if (expression == null || !ColumnDef.DefaultValue.NOW.equalsIgnoreCase(expression.getExprName()) + || expression.getPrecision() == null + || expression.getPrecision() <= DateTimeV2Type.MAX_SCALE) { + return Optional.empty(); + } + + int precision = expression.getPrecision().intValue(); + int truncationFactor = (int) Math.pow(10, TimeStampNsType.SCALE - precision); + LocalDateTime now = LocalDateTime.now(TimeUtils.getTimeZone().toZoneId()); + LocalDateTime truncated = now.withNano(now.getNano() / truncationFactor * truncationFactor); + return Optional.of(TimeStampNsLiteral.fromJavaDateType(truncated)); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java index 4094dcb5732ea7..f0c2e4f07fdea1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java @@ -64,6 +64,7 @@ import org.apache.doris.nereids.trees.expressions.literal.SmallIntLiteral; import org.apache.doris.nereids.trees.expressions.literal.StringLikeLiteral; import org.apache.doris.nereids.trees.expressions.literal.StringLiteral; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.trees.expressions.literal.TimeV2Literal; import org.apache.doris.nereids.trees.expressions.literal.TimestampTzLiteral; import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral; @@ -96,6 +97,7 @@ import org.apache.doris.nereids.types.StringType; import org.apache.doris.nereids.types.StructField; import org.apache.doris.nereids.types.StructType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.TimeV2Type; import org.apache.doris.nereids.types.TinyIntType; @@ -131,6 +133,7 @@ import java.util.Map; import java.util.Optional; import java.util.function.Function; +import java.util.function.Predicate; import java.util.stream.Collectors; /** @@ -234,6 +237,24 @@ public static Optional implicitCast(DataType input, DataType expected) * Return Optional.empty() if we cannot do implicit cast. */ public static Optional implicitCastPrimitive(DataType input, DataType expected) { + // TIMESTAMP_NS has a different physical representation from DATETIMEV2. Temporal and + // numeric inputs may be promoted to TIMESTAMP_NS now that the corresponding casts exist, + // but never implicitly demote TIMESTAMP_NS to DATETIMEV2 because that loses nanoseconds. + if (input instanceof TimeStampNsType || expected instanceof TimeStampNsType) { + if (input.equals(expected) || expected instanceof AnyDataType) { + return Optional.of(input); + } else if (input instanceof NullType) { + return Optional.of(expected.defaultConcreteType()); + } else if (expected instanceof TimeStampNsType + && (input instanceof NumericType || input.isDateLikeType() + || input instanceof TimeV2Type || input instanceof CharacterType)) { + return Optional.of(expected); + } else if (input instanceof TimeStampNsType && expected instanceof CharacterType) { + return Optional.of(expected.defaultConcreteType()); + } + return Optional.empty(); + } + Optional castType = implicitCastPrimitiveInternal(input, expected); // TODO: complete the cast logic like FunctionCallExpr.analyzeImpl boolean legacyCastCompatible = false; @@ -345,16 +366,20 @@ public static boolean hasTimestampTzType(DataType dataType) { } private static boolean hasSpecifiedType(DataType dataType, Class specifiedType) { + return hasSpecifiedType(dataType, type -> specifiedType.isAssignableFrom(type.getClass())); + } + + private static boolean hasSpecifiedType(DataType dataType, Predicate predicate) { if (dataType instanceof ArrayType) { - return hasSpecifiedType(((ArrayType) dataType).getItemType(), specifiedType); + return hasSpecifiedType(((ArrayType) dataType).getItemType(), predicate); } else if (dataType instanceof MapType) { - return hasSpecifiedType(((MapType) dataType).getKeyType(), specifiedType) - || hasSpecifiedType(((MapType) dataType).getValueType(), specifiedType); + return hasSpecifiedType(((MapType) dataType).getKeyType(), predicate) + || hasSpecifiedType(((MapType) dataType).getValueType(), predicate); } else if (dataType instanceof StructType) { return ((StructType) dataType).getFields().stream() - .anyMatch(f -> hasSpecifiedType(f.getDataType(), specifiedType)); + .anyMatch(f -> hasSpecifiedType(f.getDataType(), predicate)); } - return specifiedType.isAssignableFrom(dataType.getClass()); + return predicate.test(dataType); } /** @@ -380,6 +405,12 @@ public static DataType replaceDateTimeV2WithMax(DataType dataType) { return replaceSpecifiedType(dataType, DateTimeV2Type.class, DateTimeV2Type.MAX); } + private static DataType replaceDateLikeWithMaxPrecision(DataType dataType) { + return replaceSpecifiedType(dataType, + type -> type instanceof DateLikeType && !(type instanceof TimeStampNsType), + DateTimeV2Type.MAX); + } + /** * replace times with target precision. */ @@ -387,7 +418,7 @@ public static DataType replaceTimesWithTargetPrecision(DataType dataType, int ta return replaceSpecifiedType( replaceSpecifiedType( replaceSpecifiedType(dataType, DateTimeV2Type.class, - DateTimeV2Type.of(targetScale)), + DateTimeV2Type.of(targetScale)), TimeV2Type.class, TimeV2Type.of(targetScale)), TimeStampTzType.class, TimeStampTzType.of(targetScale)); } @@ -397,17 +428,27 @@ public static DataType replaceTimesWithTargetPrecision(DataType dataType, int ta */ public static DataType replaceSpecifiedType(DataType dataType, Class specifiedType, DataType newType) { + return replaceSpecifiedType(dataType, + type -> specifiedType.isAssignableFrom(type.getClass()), newType); + } + + private static DataType replaceSpecifiedType(DataType dataType, + Predicate shouldReplace, DataType newType) { if (dataType instanceof ArrayType) { - return ArrayType.of(replaceSpecifiedType(((ArrayType) dataType).getItemType(), specifiedType, newType)); + return ArrayType.of(replaceSpecifiedType( + ((ArrayType) dataType).getItemType(), shouldReplace, newType)); } else if (dataType instanceof MapType) { - return MapType.of(replaceSpecifiedType(((MapType) dataType).getKeyType(), specifiedType, newType), - replaceSpecifiedType(((MapType) dataType).getValueType(), specifiedType, newType)); + return MapType.of(replaceSpecifiedType( + ((MapType) dataType).getKeyType(), shouldReplace, newType), + replaceSpecifiedType( + ((MapType) dataType).getValueType(), shouldReplace, newType)); } else if (dataType instanceof StructType) { List newFields = ((StructType) dataType).getFields().stream() - .map(f -> f.withDataType(replaceSpecifiedType(f.getDataType(), specifiedType, newType))) + .map(f -> f.withDataType(replaceSpecifiedType( + f.getDataType(), shouldReplace, newType))) .collect(ImmutableList.toImmutableList()); return new StructType(newFields); - } else if (specifiedType.isAssignableFrom(dataType.getClass())) { + } else if (shouldReplace.test(dataType)) { return newType; } else { return dataType; @@ -665,6 +706,8 @@ public static Optional characterLiteralTypeCoercion(String value, Da ret = new VarcharLiteral(value, ((VarcharType) dataType).getLen()); } else if (dataType instanceof StringType) { ret = new StringLiteral(value); + } else if (dataType instanceof TimeStampNsType && DateTimeChecker.isValidDateTime(value)) { + ret = new TimeStampNsLiteral(value); } else if ((dataType.isDateTimeV2Type() || dataType.isDateTimeType()) && DateTimeChecker.isValidDateTime(value)) { ret = DateTimeLiteral.parseDateTimeLiteral(value, true).orElse(null); @@ -677,14 +720,18 @@ public static Optional characterLiteralTypeCoercion(String value, Da } ret = TimestampTzLiteral.fromSessionTimeZone(timeStampTzType, value); } else if ((dataType.isDateV2Type() || dataType.isDateType()) && DateTimeChecker.isValidDateTime(value)) { - Result parseResult = DateV2Literal.parseDateLiteral(value, true); - if (parseResult.isOk()) { - ret = parseResult.get(); + if (hasNonZeroFractionBeyondScale(value, DateTimeV2Type.MAX_SCALE)) { + ret = new TimeStampNsLiteral(value); } else { - Result parseResult2 - = DateTimeV2Literal.parseDateTimeLiteral(value, true); - if (parseResult2.isOk()) { - ret = parseResult2.get(); + Result parseResult = DateV2Literal.parseDateLiteral(value, true); + if (parseResult.isOk()) { + ret = parseResult.get(); + } else { + Result parseResult2 + = DateTimeV2Literal.parseDateTimeLiteral(value, true); + if (parseResult2.isOk()) { + ret = parseResult2.get(); + } } } } else if (dataType instanceof TimeV2Type && TimeChecker.isValidTime(value)) { @@ -702,6 +749,23 @@ public static Optional characterLiteralTypeCoercion(String value, Da } + private static boolean hasNonZeroFractionBeyondScale(String value, int scale) { + int dot = value.lastIndexOf('.'); + if (dot < 0) { + return false; + } + int fractionEnd = dot + 1; + while (fractionEnd < value.length() && Character.isDigit(value.charAt(fractionEnd))) { + fractionEnd++; + } + for (int i = dot + scale + 1; i < fractionEnd; i++) { + if (value.charAt(i) != '0') { + return true; + } + } + return false; + } + public static Expression implicitCastInputTypes(Expression expr, List expectedInputTypes) { List> inputImplicitCastTypes = getInputImplicitCastTypes(expr.children(), expectedInputTypes); @@ -984,6 +1048,8 @@ private static Optional getCommonDataTypeWithDateType(DataType leftTyp */ private static Optional getCommonDataTypeWithDateTimeV2Type( DateTimeV2Type leftType, DataType rightType) { + Preconditions.checkArgument(leftType.getClass() == DateTimeV2Type.class, + "TIMESTAMP_NS does not belong to the DATETIMEV2 precision family"); if (rightType.isNumericType()) { if (rightType instanceof IntegralType) { return Optional.of(leftType); @@ -1017,6 +1083,20 @@ private static Optional getCommonDataTypeWithDateTimeV2Type( return Optional.empty(); } + /** + * Choose TIMESTAMP_NS as the lossless common type whenever the other operand has a supported + * conversion. In particular, DATETIMEV2 must be promoted rather than truncating a nanosecond + * operand to DATETIMEV2(6). + */ + private static Optional getCommonDataTypeWithTimeStampNsType(DataType otherType) { + if (otherType instanceof TimeStampNsType || otherType.isNumericType() + || otherType.isDateLikeType() || otherType instanceof TimeV2Type + || otherType.isStringLikeType()) { + return Optional.of(TimeStampNsType.INSTANCE); + } + return Optional.empty(); + } + /** * left type must be TimeV2Type Type */ @@ -1124,16 +1204,16 @@ public static Optional findWiderTypeForTwo(DataType left, DataType rig return findCommonVariantType((VariantType) left, (VariantType) right); } else if (left instanceof VariantType) { return Optional.of(replaceSpecifiedType(replaceDecimalV3WithTarget(replaceSpecifiedType( - replaceSpecifiedType(replaceSpecifiedType(replaceCharacterToString(right), - IntegralType.class, DecimalV3Type.SYSTEM_DEFAULT), - DateLikeType.class, DateTimeV2Type.MAX), + replaceDateLikeWithMaxPrecision(replaceSpecifiedType( + replaceCharacterToString(right), + IntegralType.class, DecimalV3Type.SYSTEM_DEFAULT)), DecimalV2Type.class, DecimalV3Type.SYSTEM_DEFAULT), DecimalV3Type.SYSTEM_DEFAULT), FloatType.class, DoubleType.INSTANCE)); } else if (right instanceof VariantType) { return Optional.of(replaceSpecifiedType(replaceDecimalV3WithTarget(replaceSpecifiedType( - replaceSpecifiedType(replaceSpecifiedType(replaceCharacterToString(left), - IntegralType.class, DecimalV3Type.SYSTEM_DEFAULT), - DateLikeType.class, DateTimeV2Type.MAX), + replaceDateLikeWithMaxPrecision(replaceSpecifiedType( + replaceCharacterToString(left), + IntegralType.class, DecimalV3Type.SYSTEM_DEFAULT)), DecimalV2Type.class, DecimalV3Type.SYSTEM_DEFAULT), DecimalV3Type.SYSTEM_DEFAULT), FloatType.class, DoubleType.INSTANCE)); } else if (left instanceof ComplexDataType || right instanceof ComplexDataType) { @@ -1208,6 +1288,12 @@ private static Optional findWiderPrimitiveTypeForTwo( } } + if (leftType instanceof TimeStampNsType) { + return getCommonDataTypeWithTimeStampNsType(rightType); + } else if (rightType instanceof TimeStampNsType) { + return getCommonDataTypeWithTimeStampNsType(leftType); + } + // we process date like type first if (!leftType.isDateLikeType() && rightType.isDateLikeType()) { DataType temp = leftType; @@ -1578,6 +1664,9 @@ public static Expression processCaseWhen(CaseWhen caseWhen) { */ public static Optional findWiderCommonType(List dataTypes, boolean overflowToDouble, boolean stringIsHighPriority) { + if (containsTimeStampNsAndOnlyCompatibleTemporalTypes(dataTypes)) { + return Optional.of(TimeStampNsType.INSTANCE); + } return dataTypes.stream().map(Optional::of).reduce(Optional.of(NullType.INSTANCE), (r, c) -> { if (r.isPresent() && c.isPresent()) { @@ -1635,6 +1724,9 @@ public static Optional findWiderCommonTypeForComparison(List @Deprecated private static Optional findWiderCommonTypeForComparison( List dataTypes, boolean intStringToString) { + if (containsTimeStampNsAndOnlyCompatibleTemporalTypes(dataTypes)) { + return Optional.of(TimeStampNsType.INSTANCE); + } Map> partitioned = dataTypes.stream() .collect(Collectors.partitioningBy(TypeCoercionUtils::hasCharacterType)); List needTypeCoercion = Lists.newArrayList(Sets.newHashSet(partitioned.get(true))); @@ -1736,6 +1828,12 @@ private static Optional findCommonPrimitiveTypeForComparison( return Optional.of(leftType); } + if (leftType instanceof TimeStampNsType) { + return getCommonDataTypeWithTimeStampNsType(rightType); + } else if (rightType instanceof TimeStampNsType) { + return getCommonDataTypeWithTimeStampNsType(leftType); + } + // decimal v3 if (leftType.isDecimalV3Type() && rightType.isDecimalV3Type()) { return Optional.of(DecimalV3Type.widerDecimalV3Type( @@ -1877,6 +1975,9 @@ private static Optional findCommonPrimitiveTypeForComparison( */ @Deprecated public static Optional findWiderCommonTypeForCaseWhen(List dataTypes) { + if (containsTimeStampNsAndOnlyCompatibleTemporalTypes(dataTypes)) { + return Optional.of(TimeStampNsType.INSTANCE); + } Map> partitioned = dataTypes.stream() .collect(Collectors.partitioningBy(TypeCoercionUtils::hasCharacterType)); List needTypeCoercion = Lists.newArrayList(Sets.newHashSet(partitioned.get(true))); @@ -1898,6 +1999,19 @@ public static Optional findWiderCommonTypeForCaseWhen(List d return Optional.of(commonType); } + private static boolean containsTimeStampNsAndOnlyCompatibleTemporalTypes(List dataTypes) { + boolean containsTimeStampNs = false; + for (DataType dataType : dataTypes) { + if (dataType instanceof TimeStampNsType) { + containsTimeStampNs = true; + } else if (!dataType.isNullType() && !dataType.isDateLikeType() + && !(dataType instanceof TimeV2Type)) { + return false; + } + } + return containsTimeStampNs; + } + /** * find wider common type for two data type. */ @@ -2007,6 +2121,13 @@ public static Optional findCommonPrimitiveTypeForCaseWhen(DataType t1, return Optional.of(StringType.INSTANCE); } + if (t1 instanceof TimeStampNsType) { + return getCommonDataTypeWithTimeStampNsType(t2); + } + if (t2 instanceof TimeStampNsType) { + return getCommonDataTypeWithTimeStampNsType(t1); + } + // decimal with date should return double if ((t1.isDecimalV2Type() && t2.isDateType()) || (t2.isDecimalV2Type() && t1.isDateType())) { return Optional.of(DoubleType.INSTANCE); diff --git a/fe/fe-core/src/main/java/org/apache/doris/persist/gson/GsonUtils.java b/fe/fe-core/src/main/java/org/apache/doris/persist/gson/GsonUtils.java index a02f5bbf204b1a..3e61102801bfe7 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/persist/gson/GsonUtils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/persist/gson/GsonUtils.java @@ -59,6 +59,7 @@ import org.apache.doris.analysis.SlotRef; import org.apache.doris.analysis.StringLiteral; import org.apache.doris.analysis.StructLiteral; +import org.apache.doris.analysis.TimeStampNsLiteral; import org.apache.doris.analysis.TimeV2Literal; import org.apache.doris.analysis.TimestampArithmeticExpr; import org.apache.doris.analysis.TryCastExpr; @@ -266,6 +267,7 @@ public class GsonUtils { .registerSubtype(ArrayLiteral.class, ArrayLiteral.class.getSimpleName()) .registerSubtype(BoolLiteral.class, BoolLiteral.class.getSimpleName()) .registerSubtype(DateLiteral.class, DateLiteral.class.getSimpleName()) + .registerSubtype(TimeStampNsLiteral.class, TimeStampNsLiteral.class.getSimpleName()) .registerSubtype(IPv4Literal.class, IPv4Literal.class.getSimpleName()) .registerSubtype(IPv6Literal.class, IPv6Literal.class.getSimpleName()) .registerSubtype(JsonLiteral.class, JsonLiteral.class.getSimpleName()) diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectProcessor.java b/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectProcessor.java index c83397f58dc0e7..9dd256b70c3bea 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectProcessor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectProcessor.java @@ -888,7 +888,7 @@ private static LiteralExpr getLiteralExprFromThrift(TExprNode node) throws Analy case DECIMAL_LITERAL: return DecimalLiteralUtils.create(node.decimal_literal.value); case STRING_LITERAL: return new StringLiteral(node.string_literal.value); case JSON_LITERAL: return new JsonLiteral(node.json_literal.value); - case DATE_LITERAL: return DateLiteralUtils.createDateLiteral(node.date_literal.value, null); + case DATE_LITERAL: return DateLiteralUtils.createLiteral(node.date_literal.value, null); case IPV4_LITERAL: return new IPv4Literal(node.ipv4_literal.value); case IPV6_LITERAL: return new IPv6Literal(node.ipv6_literal.value); default: throw new AnalysisException("Wrong type from thrift;"); diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java index 902bbfb464679c..28e2473ae87ca3 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java @@ -2031,6 +2031,11 @@ protected void sendBinaryResultRow(ResultSet resultSet) throws IOException { serializer.writeInt4((int) microSecond); } break; + case TIMESTAMP_NS: + // MySQL temporal binary values cannot carry nanoseconds. The metadata advertises + // MYSQL_TYPE_STRING, so encode the result as length-encoded text. + serializer.writeLenEncodedString(item); + break; default: serializer.writeLenEncodedString(item); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/cache/PartitionRange.java b/fe/fe-core/src/main/java/org/apache/doris/qe/cache/PartitionRange.java index acdb244e482939..bbf0984a765f32 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/qe/cache/PartitionRange.java +++ b/fe/fe-core/src/main/java/org/apache/doris/qe/cache/PartitionRange.java @@ -129,6 +129,7 @@ public boolean init(Type type, LiteralExpr expr) { case TIMEV2: case DATETIME: case DATETIMEV2: + case TIMESTAMP_NS: case TIMESTAMPTZ: case FLOAT: case DOUBLE: diff --git a/fe/fe-core/src/main/java/org/apache/doris/service/arrowflight/FlightSqlSchemaHelper.java b/fe/fe-core/src/main/java/org/apache/doris/service/arrowflight/FlightSqlSchemaHelper.java index b89abf16e83395..ab77e49c3e8814 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/service/arrowflight/FlightSqlSchemaHelper.java +++ b/fe/fe-core/src/main/java/org/apache/doris/service/arrowflight/FlightSqlSchemaHelper.java @@ -134,6 +134,8 @@ private static ArrowType getArrowType(PrimitiveType primitiveType, Integer preci } else { return new ArrowType.Timestamp(TimeUnit.SECOND, timeZone); } + case TIMESTAMP_NS: + return new ArrowType.Timestamp(TimeUnit.NANOSECOND, timeZone); case TIMESTAMPTZ: if (scale > 3) { return new ArrowType.Timestamp(TimeUnit.MICROSECOND, "UTC"); diff --git a/fe/fe-core/src/main/java/org/apache/doris/statistics/util/StatisticsUtil.java b/fe/fe-core/src/main/java/org/apache/doris/statistics/util/StatisticsUtil.java index e3b67a4dd51baf..e22db8c7d7a18c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/statistics/util/StatisticsUtil.java +++ b/fe/fe-core/src/main/java/org/apache/doris/statistics/util/StatisticsUtil.java @@ -261,8 +261,9 @@ public static LiteralExpr readableValue(Type type, String columnValue) throws An case DATETIME: case DATEV2: case DATETIMEV2: + case TIMESTAMP_NS: case TIMESTAMPTZ: - return DateLiteralUtils.createDateLiteral(columnValue, type); + return DateLiteralUtils.createLiteral(columnValue, type); case CHAR: case VARCHAR: case STRING: @@ -313,6 +314,7 @@ public static double convertToDouble(Type type, String columnValue) throws Analy return literal.getDouble(); case DATETIMEV2: + case TIMESTAMP_NS: case DATETIME: DateTimeLiteral dateTimeLiteral = new DateTimeLiteral(columnValue); return dateTimeLiteral.getDouble(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java index 4d2b71f0bc6df2..594b08e0bd981a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java @@ -17,6 +17,7 @@ package org.apache.doris.tablefunction; +import org.apache.doris.analysis.DateLiteralUtils; import org.apache.doris.analysis.UserIdentity; import org.apache.doris.authentication.AuthenticationIntegrationMeta; import org.apache.doris.authentication.RoleMappingMeta; @@ -2247,6 +2248,11 @@ private static List partitionValuesRows(List partitionCols, List ColumnDef.validateDefaultValue( + Type.TIMESTAMP_NS, "CURRENT_TIMESTAMP", + new DefaultValueExprDef(ColumnDef.DefaultValue.NOW))); + Assertions.assertDoesNotThrow( + () -> ColumnDef.validateDefaultValue( + Type.TIMESTAMP_NS, "CURRENT_TIMESTAMP(9)", + new DefaultValueExprDef(ColumnDef.DefaultValue.NOW, 9L))); + } + + @Test + void testCurrentTimestampKeepsMicrosecondPrecision() { + for (long precision = 1; precision <= 9; precision++) { + String suffix = "\\.\\d{" + precision + "}"; + String pattern = "\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}" + suffix; + + ColumnDef.DefaultValue legacy = new ColumnDef.DefaultValue( + true, "CURRENT_TIMESTAMP(" + precision + ")", ColumnDef.DefaultValue.NOW, precision); + Assertions.assertTrue(legacy.getValue().matches(pattern)); + + if (precision <= 6) { + org.apache.doris.nereids.trees.plans.commands.info.DefaultValue datetimeV2 = + org.apache.doris.nereids.trees.plans.commands.info.DefaultValue + .currentTimeStampDefaultValueWithPrecision(precision); + Assertions.assertTrue(datetimeV2.getRawValue().matches(pattern)); + } + org.apache.doris.nereids.trees.plans.commands.info.DefaultValue timestampNs = + org.apache.doris.nereids.trees.plans.commands.info.DefaultValue + .currentTimeStampDefaultValueWithPrecision(precision, TimeStampNsType.INSTANCE); + Assertions.assertTrue(timestampNs.getRawValue().matches(pattern)); + } + + for (long precision = 7; precision <= 9; precision++) { + long invalidPrecision = precision; + Assertions.assertThrows(AnalysisException.class, + () -> org.apache.doris.nereids.trees.plans.commands.info.DefaultValue + .currentTimeStampDefaultValueWithPrecision(invalidPrecision)); + } + Assertions.assertThrows(AnalysisException.class, + () -> org.apache.doris.nereids.trees.plans.commands.info.DefaultValue + .currentTimeStampDefaultValueWithPrecision(10L, TimeStampNsType.INSTANCE)); + } +} diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/DateLiteralUtilsTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/DateLiteralUtilsTest.java index 08d472d54865ff..ba93be31c2eb22 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/DateLiteralUtilsTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/DateLiteralUtilsTest.java @@ -23,15 +23,23 @@ import org.apache.doris.common.util.TimeUtils; import org.apache.doris.foundation.format.FormatOptions; import org.apache.doris.qe.ConnectContext; +import org.apache.doris.thrift.TExpr; +import org.apache.doris.thrift.TExprNodeType; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.time.Instant; +import java.time.LocalDateTime; import java.util.TimeZone; public class DateLiteralUtilsTest { + private static TimeStampNsLiteral createTimeStampNsLiteral(String value) throws AnalysisException { + return (TimeStampNsLiteral) DateLiteralUtils.createLiteral( + value, ScalarType.createTimeStampNsType()); + } + @Test public void testTimestampTzInit() throws AnalysisException { String value; @@ -205,6 +213,262 @@ public void testDatetimeV2WithMicroseconds() throws AnalysisException { Assertions.assertTrue(dl0.getType().isDatetimeV2()); } + @Test + public void testTimestampNsWithNanoseconds() throws AnalysisException { + TimeStampNsLiteral dl7 = createTimeStampNsLiteral("2023-06-15 14:30:45.1234567"); + Assertions.assertTrue(dl7.getType().isTimeStampNs()); + Assertions.assertEquals(123456700, dl7.getNanosecond()); + Assertions.assertEquals(123456, dl7.getMicrosecond()); + Assertions.assertEquals("2023-06-15 14:30:45.123456700", dl7.getStringValue()); + + TimeStampNsLiteral dl8 = createTimeStampNsLiteral("2023-06-15 14:30:45.12345678"); + Assertions.assertTrue(dl8.getType().isTimeStampNs()); + Assertions.assertEquals(123456780, dl8.getNanosecond()); + Assertions.assertEquals("2023-06-15 14:30:45.123456780", dl8.getStringValue()); + + TimeStampNsLiteral dl9 = createTimeStampNsLiteral("2023-06-15 14:30:45.123456789"); + Assertions.assertTrue(dl9.getType().isTimeStampNs()); + Assertions.assertEquals(123456789, dl9.getNanosecond()); + Assertions.assertEquals("2023-06-15 14:30:45.123456789", dl9.getStringValue()); + } + + @Test + public void testDateTimeV2MaximumSentinelUsesMicroseconds() throws AnalysisException { + DateLiteral maximum = new DateLiteral(Type.DATETIMEV2_WITH_MAX_SCALAR, true); + Assertions.assertEquals("9999-12-31 23:59:59.999999", maximum.getStringValue()); + Assertions.assertEquals(999999, maximum.getMicrosecond()); + } + + @Test + public void testTimestampNsUsesFixedNanosecondPrecision() throws AnalysisException { + TimeStampNsLiteral rounded7 = createTimeStampNsLiteral("2023-06-15 14:30:45.12345675"); + TimeStampNsLiteral canonical7 = createTimeStampNsLiteral("2023-06-15 14:30:45.123456750"); + Assertions.assertEquals("2023-06-15 14:30:45.123456750", rounded7.getStringValue()); + Assertions.assertEquals(123456750, rounded7.getNanosecond()); + Assertions.assertEquals(canonical7, rounded7); + Assertions.assertEquals(canonical7.hashCode(), rounded7.hashCode()); + + TimeStampNsLiteral rounded8 = createTimeStampNsLiteral("2023-06-15 14:30:45.123456785"); + Assertions.assertEquals("2023-06-15 14:30:45.123456785", rounded8.getStringValue()); + Assertions.assertEquals(123456785, rounded8.getNanosecond()); + + TimeStampNsLiteral rounded9 = createTimeStampNsLiteral("2023-06-15 14:30:45.1234567895"); + Assertions.assertEquals("2023-06-15 14:30:45.123456790", rounded9.getStringValue()); + Assertions.assertEquals(123456790, rounded9.getNanosecond()); + + TimeStampNsLiteral carry7 = createTimeStampNsLiteral("2023-06-15 14:30:45.99999995"); + TimeStampNsLiteral carry8 = createTimeStampNsLiteral("2023-06-15 14:30:45.999999995"); + TimeStampNsLiteral carry9 = createTimeStampNsLiteral("2023-06-15 14:30:45.9999999995"); + Assertions.assertEquals("2023-06-15 14:30:45.999999950", carry7.getStringValue()); + Assertions.assertEquals("2023-06-15 14:30:45.999999995", carry8.getStringValue()); + Assertions.assertEquals("2023-06-15 14:30:46.000000000", carry9.getStringValue()); + } + + @Test + public void testTimestampNsRoundFloorRequiresFixedScale() throws AnalysisException { + TimeStampNsLiteral timestampNs = createTimeStampNsLiteral("2023-06-15 14:30:45.123456789"); + + timestampNs.roundFloor(ScalarType.TIMESTAMP_NS_SCALE); + Assertions.assertEquals(123456789, timestampNs.getNanosecond()); + + int[] invalidScales = {-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10}; + for (int scale : invalidScales) { + IllegalArgumentException exception = Assertions.assertThrows( + IllegalArgumentException.class, () -> timestampNs.roundFloor(scale)); + Assertions.assertEquals("TIMESTAMP_NS has fixed scale " + ScalarType.TIMESTAMP_NS_SCALE + + ", but got " + scale, exception.getMessage()); + Assertions.assertEquals(123456789, timestampNs.getNanosecond()); + } + } + + @Test + public void testTimestampNsTypeInference() throws AnalysisException { + // An explicit DATETIME target keeps its legacy six-digit input contract. TIMESTAMP_NS is + // a distinct type and must not be selected merely because a DATETIME input has more digits. + Assertions.assertThrows(AnalysisException.class, () -> DateLiteralUtils.createLiteral( + "2023-06-15 14:30:45.123456789", Type.DATETIME)); + + TimeStampNsLiteral inferredScale7 = (TimeStampNsLiteral) DateLiteralUtils.createLiteral( + "2023-06-15 14:30:45.123456700", null); + Assertions.assertTrue(inferredScale7.getType().isTimeStampNs()); + Assertions.assertEquals(123456700, inferredScale7.getNanosecond()); + Assertions.assertEquals("2023-06-15 14:30:45.123456700", inferredScale7.getStringValue()); + + TimeStampNsLiteral inferredScale9 = (TimeStampNsLiteral) DateLiteralUtils.createLiteral( + "1970-01-01 00:00:00.000000001", null); + Assertions.assertTrue(inferredScale9.getType().isTimeStampNs()); + Assertions.assertEquals(1, inferredScale9.getNanosecond()); + Assertions.assertEquals(1L, inferredScale9.getRealValue()); + + TimeStampNsLiteral inferredWithGuardDigit = (TimeStampNsLiteral) DateLiteralUtils.createLiteral( + "2023-06-15 14:30:45.1234567895", null); + Assertions.assertEquals("2023-06-15 14:30:45.123456790", + inferredWithGuardDigit.getStringValue()); + + TimeStampNsLiteral inferredFromGuardDigit = (TimeStampNsLiteral) DateLiteralUtils.createLiteral( + "2023-06-15 14:30:45.1234560005", null); + Assertions.assertEquals("2023-06-15 14:30:45.123456001", + inferredFromGuardDigit.getStringValue()); + } + + @Test + public void testTimestampTzDoesNotAcceptNanosecondInput() { + Assertions.assertThrows(AnalysisException.class, () -> DateLiteralUtils.createLiteral( + "2023-06-15 14:30:45.123456789+00:00", ScalarType.createTimeStampTzType(6))); + } + + @Test + public void testTimestampNsEpochAndBoundaries() throws AnalysisException { + TimeStampNsLiteral beforeEpoch = createTimeStampNsLiteral("1969-12-31 23:59:59.999999999"); + Assertions.assertEquals(-1L, beforeEpoch.getRealValue()); + + TimeStampNsLiteral epoch = createTimeStampNsLiteral("1970-01-01 00:00:00.000000000"); + Assertions.assertEquals(0L, epoch.getRealValue()); + + TimeStampNsLiteral lowerBoundary = createTimeStampNsLiteral("1677-09-21 00:12:43.145224192"); + Assertions.assertEquals(Long.MIN_VALUE, lowerBoundary.getRealValue()); + + TimeStampNsLiteral upperBoundary = createTimeStampNsLiteral("2262-04-11 23:47:16.854775807"); + Assertions.assertEquals(Long.MAX_VALUE, upperBoundary.getRealValue()); + + TimeStampNsLiteral minimum = new TimeStampNsLiteral(false); + Assertions.assertEquals(Long.MIN_VALUE, minimum.getRealValue()); + Assertions.assertTrue(minimum.isMinValue()); + + TimeStampNsLiteral maximum = new TimeStampNsLiteral(true); + Assertions.assertEquals(Long.MAX_VALUE, maximum.getRealValue()); + + epoch.setMinValue(); + Assertions.assertEquals(Long.MIN_VALUE, epoch.getRealValue()); + Assertions.assertTrue(epoch.isMinValue()); + } + + @Test + public void testTimestampNsDateArithmeticPreservesLiteralType() throws AnalysisException { + TimeStampNsLiteral literal = new TimeStampNsLiteral( + 1970, 1, 1, 0, 0, 0, 123456789); + + TimeStampNsLiteral result = literal.plusSeconds(1).plusDays(1); + + Assertions.assertInstanceOf(TimeStampNsLiteral.class, result); + Assertions.assertEquals("1970-01-02 00:00:01.123456789", result.getStringValue()); + Assertions.assertEquals(86401123456789L, result.getRealValue()); + } + + @Test + public void testTimestampNsIsIndependentFromDateLiteral() throws AnalysisException { + TimeStampNsLiteral timestampNs = createTimeStampNsLiteral( + "2024-01-02 03:04:05.123456000"); + DateLiteral datetimeV2 = DateLiteralUtils.createDateLiteral( + "2024-01-02 03:04:05.123456", ScalarType.createDatetimeV2Type(6)); + + Assertions.assertInstanceOf(LiteralExpr.class, timestampNs); + Assertions.assertFalse(DateLiteral.class.isInstance(timestampNs)); + Assertions.assertEquals(0, timestampNs.compareLiteral(datetimeV2)); + Assertions.assertEquals(0, datetimeV2.compareLiteral(timestampNs)); + Assertions.assertEquals(timestampNs, datetimeV2); + Assertions.assertEquals(datetimeV2, timestampNs); + Assertions.assertEquals(datetimeV2.hashCode(), timestampNs.hashCode()); + Assertions.assertInstanceOf(TimeStampNsLiteral.class, timestampNs.clone()); + DateLiteral dateV2 = new DateLiteral(2024, 1, 2, Type.DATEV2); + TimeStampNsLiteral timestampAtMidnight = new TimeStampNsLiteral( + 2024, 1, 2, 0, 0, 0, 0); + Assertions.assertTrue(dateV2.compareLiteral(timestampAtMidnight) < 0); + Assertions.assertTrue(timestampAtMidnight.compareLiteral(dateV2) > 0); + TimeStampNsLiteral oneNanosecondLater = new TimeStampNsLiteral( + 2024, 1, 2, 0, 0, 0, 1); + Assertions.assertTrue(timestampAtMidnight.compareLiteral(oneNanosecondLater) < 0); + Assertions.assertEquals("'2024-01-02 03:04:05.123456000'", + timestampNs.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); + TExpr thrift = ExprToThriftVisitor.treeToThrift(timestampNs); + Assertions.assertEquals(TExprNodeType.DATE_LITERAL, thrift.nodes.get(0).node_type); + Assertions.assertEquals(timestampNs.getStringValue(), thrift.nodes.get(0).date_literal.value); + + Assertions.assertThrows(AnalysisException.class, () -> DateLiteralUtils.createDateLiteral( + timestampNs.getStringValue(), ScalarType.createTimeStampNsType())); + } + + @Test + public void testTimestampNsCheckRangeUsesInt64EpochNanosecondBounds() { + Assertions.assertFalse(new TimeStampNsLiteral( + 1677, 9, 21, 0, 12, 43, 145224192).checkRange()); + Assertions.assertTrue(new TimeStampNsLiteral( + 1677, 9, 21, 0, 12, 43, 145224191).checkRange()); + Assertions.assertFalse(new TimeStampNsLiteral( + 2262, 4, 11, 23, 47, 16, 854775807).checkRange()); + Assertions.assertTrue(new TimeStampNsLiteral( + 2262, 4, 11, 23, 47, 16, 854775808).checkRange()); + TimeStampNsLiteral beforeMinimumYear = new TimeStampNsLiteral( + 1676, 12, 31, 23, 59, 59, 999999999); + Assertions.assertTrue(beforeMinimumYear.checkRange()); + AnalysisException beforeMinimumYearException = Assertions.assertThrows( + AnalysisException.class, beforeMinimumYear::checkValueValid); + Assertions.assertTrue(beforeMinimumYearException.getMessage().contains("invalid year value: 1676")); + TimeStampNsLiteral afterMaximumYear = new TimeStampNsLiteral( + 2263, 1, 1, 0, 0, 0, 0); + Assertions.assertTrue(afterMaximumYear.checkRange()); + AnalysisException afterMaximumYearException = Assertions.assertThrows( + AnalysisException.class, afterMaximumYear::checkValueValid); + Assertions.assertTrue(afterMaximumYearException.getMessage().contains("invalid year value: 2263")); + Assertions.assertTrue(new TimeStampNsLiteral( + 2024, 13, 1, 0, 0, 0, 0).checkRange()); + + DateLiteral maxDatetimeV2 = new DateLiteral( + 9999, 12, 31, 23, 59, 59, 999999, ScalarType.createDatetimeV2Type(6)); + Assertions.assertFalse(maxDatetimeV2.checkRange()); + } + + @Test + public void testFractionalSecondRangeIsTypeSpecific() throws AnalysisException { + LocalDateTime lastMicrosecond = LocalDateTime.of(2024, 1, 1, 0, 0, 0, 999999000); + LocalDateTime afterLastMicrosecond = LocalDateTime.of(2024, 1, 1, 0, 0, 0, 999999001); + + for (Type type : new Type[] { + ScalarType.createDatetimeV2Type(6), ScalarType.createTimeStampTzType(6)}) { + DateLiteral valid = new DateLiteral(lastMicrosecond, type); + Assertions.assertFalse(valid.checkRange()); + Assertions.assertDoesNotThrow(valid::checkValueValid); + + DateLiteral canonicalized = new DateLiteral(afterLastMicrosecond, type); + Assertions.assertEquals(999999, canonicalized.getMicrosecond()); + Assertions.assertFalse(canonicalized.checkRange()); + Assertions.assertDoesNotThrow(canonicalized::checkValueValid); + } + + TimeStampNsLiteral timestampNs = new TimeStampNsLiteral( + LocalDateTime.of(2024, 1, 1, 0, 0, 0, 999999999)); + Assertions.assertFalse(timestampNs.checkRange()); + Assertions.assertDoesNotThrow(timestampNs::checkValueValid); + + TimeStampNsLiteral invalidTimestampNs = new TimeStampNsLiteral( + 2024, 1, 1, 0, 0, 0, 1000000000L); + Assertions.assertTrue(invalidTimestampNs.checkRange()); + Assertions.assertThrows(AnalysisException.class, invalidTimestampNs::checkValueValid); + } + + @Test + public void testTimestampNsTimezoneOffset() throws AnalysisException { + TimeStampNsLiteral utc = createTimeStampNsLiteral("2023-06-15 12:00:00.123456789+00:00"); + TimeStampNsLiteral plus8 = createTimeStampNsLiteral("2023-06-15 20:00:00.123456789+08:00"); + TimeStampNsLiteral minus5 = createTimeStampNsLiteral("2023-06-15 07:00:00.123456789-05:00"); + + Assertions.assertEquals(utc.getStringValue(), plus8.getStringValue()); + Assertions.assertEquals(utc.getStringValue(), minus5.getStringValue()); + Assertions.assertEquals(123456789, utc.getNanosecond()); + Assertions.assertEquals(123456789, plus8.getNanosecond()); + Assertions.assertEquals(123456789, minus5.getNanosecond()); + } + + @Test + public void testInvalidTimestampNsseconds() { + Assertions.assertThrows(AnalysisException.class, () -> DateLiteralUtils.createLiteral( + "2023-02-29 14:30:45.123456789", ScalarType.createTimeStampNsType())); + Assertions.assertThrows(AnalysisException.class, () -> DateLiteralUtils.createLiteral( + "1677-09-21 00:12:43.145224191", ScalarType.createTimeStampNsType())); + Assertions.assertThrows(AnalysisException.class, () -> DateLiteralUtils.createLiteral( + "2262-04-11 23:47:16.854775808", ScalarType.createTimeStampNsType())); + } + @Test public void testCompactDateFormats() throws AnalysisException { // YYYYMMDD compact date diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprGsonSerializationTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprGsonSerializationTest.java index 83b057759ed5a5..5eda48b0d0251b 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprGsonSerializationTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprGsonSerializationTest.java @@ -146,6 +146,8 @@ private Map, Expr> createExprSamples() throws Exception { samples.put(StringLiteral.class, new StringLiteral("expr-gson")); samples.put(StructLiteral.class, new StructLiteral(new StructType(), new IntLiteral(7L), new StringLiteral("field"))); + samples.put(TimeStampNsLiteral.class, + new TimeStampNsLiteral(2024, 4, 27, 12, 34, 56, 123456789)); samples.put(TimeV2Literal.class, new TimeV2Literal(12, 34, 56, 123456, 6, false)); samples.put(VarBinaryLiteral.class, new VarBinaryLiteral("bin".getBytes(StandardCharsets.UTF_8))); samples.put(BetweenPredicate.class, createBetweenPredicate()); diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprToStringValueVisitorTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprToStringValueVisitorTest.java index 9391d622cc6226..7b3d741b60b089 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprToStringValueVisitorTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprToStringValueVisitorTest.java @@ -319,6 +319,17 @@ public void testDateLiteralInComplexType() throws Exception { V.visitDateLiteral(d, StringValueContext.forQuery(FormatOptions.getDefault()).asComplexType())); } + @Test + public void testTimeStampNsLiteral() { + TimeStampNsLiteral timestampNs = new TimeStampNsLiteral( + 2024, 1, 15, 10, 30, 0, 123456789); + Assertions.assertEquals("2024-01-15 10:30:00.123456789", + timestampNs.accept(V, StringValueContext.forQuery(FormatOptions.getDefault()))); + Assertions.assertEquals("\"2024-01-15 10:30:00.123456789\"", + timestampNs.accept(V, + StringValueContext.forQuery(FormatOptions.getDefault()).asComplexType())); + } + // ======================== TimeStampTz ======================== @Test diff --git a/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateFunctionTest.java b/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateFunctionTest.java index 977d11c24a9141..819507304dc2d7 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateFunctionTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateFunctionTest.java @@ -155,6 +155,12 @@ public void testCreatePythonFunctionRejectsObjectTypes() throws Exception { assertCreateFunctionAnalysisException(ctx, "create function py_obj_type_db.j_bitmap_arg(bitmap) returns int " + "properties('type'='JAVA_UDF', 'symbol'='evaluate');", "JAVA_UDF does not support argument 1 type bitmap"); + createFunction("create function py_obj_type_db.j_timestamp_ns(timestamp_ns) returns timestamp_ns " + + "properties('type'='JAVA_UDF', " + + "'symbol'='org.apache.doris.catalog.TimestampNsUdf');", ctx); + createFunction("create function py_obj_type_db.j_timestamp_ns_array(array) " + + "returns array properties('type'='JAVA_UDF', " + + "'symbol'='org.apache.doris.catalog.TimestampNsUdf');", ctx); assertCreateFunctionAnalysisException(ctx, "create function py_obj_type_db.py_hll_ret(int) returns hll " + "properties('type'='PYTHON_UDF', 'symbol'='evaluate', 'runtime_version'='3.10.2');", "PYTHON_UDF does not support return type hll"); diff --git a/fe/fe-core/src/test/java/org/apache/doris/catalog/PartitionKeyTest.java b/fe/fe-core/src/test/java/org/apache/doris/catalog/PartitionKeyTest.java index b5148f982eacf7..65d56ec8a95946 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/catalog/PartitionKeyTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/PartitionKeyTest.java @@ -27,6 +27,8 @@ import org.junit.BeforeClass; import org.junit.Test; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.nio.file.Files; @@ -292,6 +294,60 @@ public void testMaxValueToSql() throws Exception { Assert.assertEquals("(MAXVALUE, MAXVALUE, MAXVALUE, MAXVALUE, MAXVALUE, MAXVALUE, MAXVALUE)", key.toSql()); } + @Test + public void testTimeStampNsMinValue() throws Exception { + assertTimeStampNsMinValue( + "1677-09-21 00:12:43.145224192", "1677-09-21 00:12:43.145224193"); + } + + @Test + public void testTimeStampNsSuccessor() throws Exception { + Column column = new Column("timestamp_ns", ScalarType.createTimeStampNsType()); + PartitionKey key = PartitionKey.createPartitionKey( + Arrays.asList(new PartitionValue("1970-01-01 00:00:00.123456789")), + Arrays.asList(column)); + + PartitionKey successor = key.successor(); + + Assert.assertTrue(successor.getKeys().get(0) + instanceof org.apache.doris.analysis.TimeStampNsLiteral); + Assert.assertEquals("1970-01-01 00:00:00.123456790", + successor.getKeys().get(0).getStringValue()); + } + + @Test + public void testTimeStampNsSerialization() throws Exception { + Column column = new Column("timestamp_ns", ScalarType.createTimeStampNsType()); + PartitionKey key = PartitionKey.createPartitionKey( + Arrays.asList(new PartitionValue("1970-01-01 00:00:00.123456789")), + Arrays.asList(column)); + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + key.write(new DataOutputStream(bytes)); + PartitionKey restored = PartitionKey.read( + new DataInputStream(new ByteArrayInputStream(bytes.toByteArray()))); + + Assert.assertEquals(key, restored); + Assert.assertTrue(restored.getKeys().get(0) + instanceof org.apache.doris.analysis.TimeStampNsLiteral); + Assert.assertEquals("1970-01-01 00:00:00.123456789", + restored.getKeys().get(0).getStringValue()); + } + + private void assertTimeStampNsMinValue(String minValue, String nextValue) throws Exception { + Column column = new Column("timestamp_ns", ScalarType.createTimeStampNsType()); + PartitionKey infinityMin = PartitionKey.createInfinityPartitionKey(Arrays.asList(column), false); + PartitionKey literalMin = PartitionKey.createPartitionKey( + Arrays.asList(new PartitionValue(minValue)), Arrays.asList(column)); + PartitionKey literalNext = PartitionKey.createPartitionKey( + Arrays.asList(new PartitionValue(nextValue)), Arrays.asList(column)); + + Assert.assertTrue(infinityMin.isMinValue()); + Assert.assertTrue(literalMin.isMinValue()); + Assert.assertEquals(infinityMin, literalMin); + Assert.assertFalse(literalNext.isMinValue()); + } + @Test public void testTimestampTzPartitionKeyKeepsExplicitOffset() throws Exception { boolean originalRunningUnitTest = FeConstants.runningUnitTest; diff --git a/fe/fe-core/src/test/java/org/apache/doris/catalog/TimestampNsUdf.java b/fe/fe-core/src/test/java/org/apache/doris/catalog/TimestampNsUdf.java new file mode 100644 index 00000000000000..e4bd2b46ad79d9 --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/TimestampNsUdf.java @@ -0,0 +1,32 @@ +// 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. + +package org.apache.doris.catalog; + +import java.time.LocalDateTime; +import java.util.List; + +/** Test fixture used to validate scalar and nested TIMESTAMP_NS Java UDF signatures. */ +public class TimestampNsUdf { + public LocalDateTime evaluate(LocalDateTime value) { + return value; + } + + public List evaluate(List value) { + return value; + } +} diff --git a/fe/fe-core/src/test/java/org/apache/doris/catalog/TypeTest.java b/fe/fe-core/src/test/java/org/apache/doris/catalog/TypeTest.java index 2029d05c082c76..f0a7b0aa7165de 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/catalog/TypeTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/TypeTest.java @@ -259,5 +259,19 @@ public void testDatetimeV2ScaleMatching() { Assert.assertFalse(Type.matchExactType(dtv2s3, dtv2s6, true)); // Same scale -> match Assert.assertTrue(Type.matchExactType(dtv2s6, ScalarType.createDatetimeV2Type(6), false)); + + ScalarType timestampNs = ScalarType.createTimeStampNsType(); + Assert.assertNotEquals(timestampNs, dtv2s6); + for (int invalidScale = 7; invalidScale <= 9; invalidScale++) { + ScalarType invalidDatetimeV2 = ScalarType.createDatetimeV2Type(invalidScale); + Assert.assertTrue(invalidDatetimeV2.isDatetimeV2()); + Assert.assertFalse(invalidDatetimeV2.isTimeStampNs()); + Assert.assertNotEquals(timestampNs, invalidDatetimeV2); + } + ScalarType wildcardDatetimeV2 = ScalarType.createDatetimeV2Type(-1); + Assert.assertFalse(timestampNs.matchesType(wildcardDatetimeV2)); + Assert.assertFalse(timestampNs.matchesType(dtv2s6)); + Assert.assertFalse(dtv2s6.matchesType(timestampNs)); + Assert.assertFalse(Type.matchExactType(timestampNs, wildcardDatetimeV2, false)); } } diff --git a/fe/fe-core/src/test/java/org/apache/doris/datasource/connector/converter/ExprToConnectorExpressionConverterTimestampNsTest.java b/fe/fe-core/src/test/java/org/apache/doris/datasource/connector/converter/ExprToConnectorExpressionConverterTimestampNsTest.java new file mode 100644 index 00000000000000..0929218b17c988 --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/datasource/connector/converter/ExprToConnectorExpressionConverterTimestampNsTest.java @@ -0,0 +1,41 @@ +// 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. + +package org.apache.doris.datasource.connector.converter; + +import org.apache.doris.analysis.TimeStampNsLiteral; +import org.apache.doris.connector.spi.pushdown.ConnectorLiteral; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.time.LocalDateTime; + +class ExprToConnectorExpressionConverterTimestampNsTest { + + @Test + void timestampNsLiteralKeepsNanosecondsAtConnectorBoundary() { + TimeStampNsLiteral literal = new TimeStampNsLiteral( + 1969, 12, 31, 23, 59, 59, 999999999); + ConnectorLiteral converted = (ConnectorLiteral) + ExprToConnectorExpressionConverter.convert(literal); + + Assertions.assertEquals("TIMESTAMP_NS", converted.getType().getTypeName()); + Assertions.assertEquals( + LocalDateTime.of(1969, 12, 31, 23, 59, 59, 999999999), converted.getValue()); + } +} diff --git a/fe/fe-core/src/test/java/org/apache/doris/mtmv/MTMVPartitionUtilTest.java b/fe/fe-core/src/test/java/org/apache/doris/mtmv/MTMVPartitionUtilTest.java index 80f91de79125cc..70e450cf987020 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/mtmv/MTMVPartitionUtilTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/mtmv/MTMVPartitionUtilTest.java @@ -19,10 +19,14 @@ import org.apache.doris.analysis.PartitionKeyDesc; import org.apache.doris.analysis.PartitionValue; +import org.apache.doris.catalog.Column; import org.apache.doris.catalog.DatabaseIf; import org.apache.doris.catalog.MTMV; import org.apache.doris.catalog.OlapTable; import org.apache.doris.catalog.Partition; +import org.apache.doris.catalog.PartitionKey; +import org.apache.doris.catalog.RangePartitionItem; +import org.apache.doris.catalog.ScalarType; import org.apache.doris.catalog.info.TableNameInfo; import org.apache.doris.common.AnalysisException; import org.apache.doris.datasource.CatalogIf; @@ -31,6 +35,7 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.collect.Range; import com.google.common.collect.Sets; import org.junit.After; import org.junit.Assert; @@ -206,6 +211,45 @@ public void testGeneratePartitionName() { Assert.assertEquals("p_1_2", rangeName); } + @Test + public void testGeneratePartitionNameFromDateTimeV2Range() throws AnalysisException { + List columns = Lists.newArrayList( + new Column("ts", ScalarType.createDatetimeV2Type(6))); + PartitionKey lower = PartitionKey.createPartitionKey( + Lists.newArrayList(new PartitionValue("2024-10-26 00:00:00")), columns); + PartitionKey upper = PartitionKey.createPartitionKey( + Lists.newArrayList(new PartitionValue("2024-10-27 00:00:00")), columns); + PartitionKeyDesc rangeDesc = new RangePartitionItem(Range.closedOpen(lower, upper)).toPartitionKeyDesc(); + + Assert.assertEquals(0, ((ScalarType) lower.getKeys().get(0).getType()).getScalarScale()); + Assert.assertEquals(PartitionKeyDesc.createFixed( + Lists.newArrayList(new PartitionValue("2024-10-26 00:00:00")), + Lists.newArrayList(new PartitionValue("2024-10-27 00:00:00"))), + rangeDesc); + Assert.assertEquals("p_20241026000000_20241027000000", + MTMVPartitionUtil.generatePartitionName(rangeDesc)); + + lower = PartitionKey.createPartitionKey( + Lists.newArrayList(new PartitionValue("2024-10-26 00:00:00.123000")), columns); + upper = PartitionKey.createPartitionKey( + Lists.newArrayList(new PartitionValue("2024-10-27 00:00:00.654000")), columns); + rangeDesc = new RangePartitionItem(Range.closedOpen(lower, upper)).toPartitionKeyDesc(); + + Assert.assertEquals(3, ((ScalarType) lower.getKeys().get(0).getType()).getScalarScale()); + Assert.assertEquals("p_20241026000000123_20241027000000654", + MTMVPartitionUtil.generatePartitionName(rangeDesc)); + + columns = Lists.newArrayList(new Column("ts", ScalarType.createTimeStampNsType())); + lower = PartitionKey.createPartitionKey( + Lists.newArrayList(new PartitionValue("2024-10-26 00:00:00.000000000")), columns); + upper = PartitionKey.createPartitionKey( + Lists.newArrayList(new PartitionValue("2024-10-27 00:00:00.000000000")), columns); + rangeDesc = new RangePartitionItem(Range.closedOpen(lower, upper)).toPartitionKeyDesc(); + + Assert.assertEquals("p_20241026000000000000000_20241027000000000000000", + MTMVPartitionUtil.generatePartitionName(rangeDesc)); + } + @Test public void testIsTableExcluded() { Set excludedTriggerTables = Sets.newHashSet(new TableNameInfo("table1")); diff --git a/fe/fe-core/src/test/java/org/apache/doris/mysql/MysqlSerializerDateTimeTest.java b/fe/fe-core/src/test/java/org/apache/doris/mysql/MysqlSerializerDateTimeTest.java new file mode 100644 index 00000000000000..924e07755f66de --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/mysql/MysqlSerializerDateTimeTest.java @@ -0,0 +1,72 @@ +// 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. + +package org.apache.doris.mysql; + +import org.apache.doris.catalog.MysqlColType; +import org.apache.doris.catalog.ScalarType; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class MysqlSerializerDateTimeTest { + private static int skipLenEncodedString(byte[] buffer, int offset) { + return offset + 1 + (buffer[offset] & 0xFF); + } + + private static int fieldMetadataOffset(byte[] buffer) { + int offset = 0; + for (int i = 0; i < 6; i++) { + offset = skipLenEncodedString(buffer, offset); + } + return offset + 1; + } + + @Test + public void testTimestampNsMetadata() { + MysqlSerializer serializer = MysqlSerializer.newInstance(); + ScalarType type = ScalarType.createTimeStampNsType(); + Assertions.assertTrue(type.isTimeStampNs()); + Assertions.assertEquals(29, serializer.getMysqlTypeLength(type)); + Assertions.assertEquals(0, serializer.getMysqlDecimals(type)); + + serializer.writeField("dt", type); + byte[] field = serializer.toArray(); + int metadataOffset = fieldMetadataOffset(field); + int mysqlTypeOffset = metadataOffset + 2 + 4; + Assertions.assertEquals(MysqlColType.MYSQL_TYPE_STRING.getCode(), + field[mysqlTypeOffset] & 0xFF); + int decimalsOffset = mysqlTypeOffset + 1 + 2; + Assertions.assertEquals(0, field[decimalsOffset] & 0xFF); + } + + @Test + public void testDatetimeV2MicrosecondMetadata() { + for (int scale = 0; scale <= 6; scale++) { + MysqlSerializer serializer = MysqlSerializer.newInstance(); + ScalarType type = ScalarType.createDatetimeV2Type(scale); + Assertions.assertEquals(scale, serializer.getMysqlDecimals(type)); + + serializer.writeField("dt", type); + byte[] field = serializer.toArray(); + int metadataOffset = fieldMetadataOffset(field); + int mysqlTypeOffset = metadataOffset + 2 + 4; + Assertions.assertEquals(MysqlColType.MYSQL_TYPE_DATETIME.getCode(), + field[mysqlTypeOffset] & 0xFF); + } + } +} diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinderTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinderTest.java index a63e4a3e6282a2..916358cefbc7b2 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinderTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinderTest.java @@ -75,6 +75,7 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.YearsSub; import org.apache.doris.nereids.trees.expressions.literal.DateTimeV2Literal; import org.apache.doris.nereids.trees.expressions.literal.Interval; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral; import org.apache.doris.nereids.types.TinyIntType; @@ -118,6 +119,23 @@ public class DatetimeFunctionBinderTest { private final DateTimeV2Literal dateTimeV2Literal1 = new DateTimeV2Literal("2024-12-01"); private final DateTimeV2Literal dateTimeV2Literal2 = new DateTimeV2Literal("2024-12-26"); + private final TimeStampNsLiteral timeStampNsLiteral + = new TimeStampNsLiteral("2024-12-01 12:34:56.123456789"); + + @Test + void testTimeStampNsDateFloorAndCeilUseImplicitOrigin() { + Expression floor = DatetimeFunctionBinder.INSTANCE.bind(new UnboundFunction( + "date_floor", ImmutableList.of(timeStampNsLiteral, secondInterval))); + Assertions.assertInstanceOf(SecondFloor.class, floor); + Assertions.assertEquals(2, floor.arity()); + Assertions.assertEquals(timeStampNsLiteral, floor.child(0)); + + Expression ceil = DatetimeFunctionBinder.INSTANCE.bind(new UnboundFunction( + "date_ceil", ImmutableList.of(timeStampNsLiteral, secondInterval))); + Assertions.assertInstanceOf(SecondCeil.class, ceil); + Assertions.assertEquals(2, ceil.arity()); + Assertions.assertEquals(timeStampNsLiteral, ceil.child(0)); + } @Test void testTimestampDiff() { diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/FoldConstantTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/FoldConstantTest.java index 9f46a7970a2c72..56b93a43bc5b07 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/FoldConstantTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/FoldConstantTest.java @@ -115,6 +115,7 @@ import org.apache.doris.nereids.trees.expressions.literal.Literal; import org.apache.doris.nereids.trees.expressions.literal.NullLiteral; import org.apache.doris.nereids.trees.expressions.literal.StringLiteral; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral; import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral; import org.apache.doris.nereids.trees.plans.RelationId; @@ -125,6 +126,7 @@ import org.apache.doris.nereids.types.IntegerType; import org.apache.doris.nereids.types.TinyIntType; import org.apache.doris.nereids.types.VarcharType; +import org.apache.doris.nereids.types.VariantType; import org.apache.doris.nereids.util.MemoTestUtils; import com.google.common.collect.ImmutableList; @@ -276,6 +278,20 @@ void testCastFold() { Expression rewritten = executor.rewrite(c, context); Literal expected = Literal.of((byte) 1); Assertions.assertEquals(rewritten, expected); + + // VARIANT values do not have an FE literal representation and must be evaluated by BE. + Cast timestampNsToVariant = new Cast( + new TimeStampNsLiteral("2024-02-29 12:34:56.123456789"), VariantType.INSTANCE); + rewritten = executor.rewrite(timestampNsToVariant, context); + Assertions.assertEquals(timestampNsToVariant, rewritten); + + Cast integerToVariant = new Cast(new IntegerLiteral(1), VariantType.INSTANCE); + rewritten = executor.rewrite(integerToVariant, context); + Assertions.assertEquals(integerToVariant, rewritten); + + Cast timestampNsToDouble = new Cast(timestampNsToVariant.child(), DoubleType.INSTANCE); + rewritten = executor.rewrite(timestampNsToDouble, context); + Assertions.assertEquals(new DoubleLiteral(20240229123456D), rewritten); } @Test @@ -331,7 +347,8 @@ void testFoldDate() { MilliSecondsAdd millisecondsAdd = new MilliSecondsAdd( DateTimeV2Literal.fromJavaDateType(LocalDateTime.of(1, 1, 1, 1, 1, 1)), new BigIntLiteral(1)); rewritten = executor.rewrite(millisecondsAdd, context); - Assertions.assertEquals(new DateTimeV2Literal(DateTimeV2Type.MAX, "0001-01-01 01:01:01.001000"), rewritten); + Assertions.assertEquals( + new DateTimeV2Literal(DateTimeV2Type.of(6), "0001-01-01 01:01:01.001000"), rewritten); // fail to fold, because the result is out of range millisecondsAdd = new MilliSecondsAdd( DateTimeV2Literal.fromJavaDateType(LocalDateTime.of(9999, 12, 31, 23, 59, 59)), @@ -1313,6 +1330,68 @@ void testDateTimeV2TypeDateTimeArithmeticFunctions() { .secondCeil(new DateTimeV2Literal("2021-01-01 12:12:12.123"), new IntegerLiteral(2))) == 0); Assertions.assertTrue(new DateTimeV2Literal("2021-01-01 12:12:12.000000").compareTo((ComparableLiteral) TimeRoundSeries .secondFloor(new DateTimeV2Literal("2021-01-01 12:12:12.123"), new IntegerLiteral(2))) == 0); + + } + + @Test + void testTimeStampNsDateTimeFunctions() { + TimeStampNsLiteral beforeEpoch = new TimeStampNsLiteral("1969-12-31 23:59:59.999999999"); + TimeStampNsLiteral epoch = new TimeStampNsLiteral("1970-01-01 00:00:00.000000000"); + TimeStampNsLiteral normal = new TimeStampNsLiteral("2024-02-29 12:34:56.123456789"); + + Assertions.assertEquals("'1970-01-01 00:00:00.999999999'", + DateTimeArithmetic.secondsAdd(beforeEpoch, new BigIntLiteral(1)).toSql()); + Assertions.assertEquals("'1970-01-01 00:00:00.000000999'", + DateTimeArithmetic.microSecondsAdd(beforeEpoch, new BigIntLiteral(1)).toSql()); + Assertions.assertEquals("'2024-03-01 12:34:56.123456789'", + DateTimeArithmetic.daysAdd(normal, new IntegerLiteral(1)).toSql()); + Assertions.assertEquals("2024", DateTimeExtractAndTransform.year(normal).toSql()); + Assertions.assertEquals("123456", DateTimeExtractAndTransform.microsecond(normal).toSql()); + Assertions.assertEquals("'2024-02-29 12:34:56.123456'", DateTimeExtractAndTransform + .dateFormat(normal, new VarcharLiteral("%Y-%m-%d %H:%i:%s.%f")).toSql()); + Assertions.assertEquals("'2024-02-29 12:34:56.000000000'", DateTimeExtractAndTransform + .dateTrunc(normal, new VarcharLiteral("second")).toSql()); + + Assertions.assertEquals("1", DateTimeExtractAndTransform.microsecondsDiff( + new TimeStampNsLiteral("1970-01-01 00:00:00.000001999"), epoch).toSql()); + Assertions.assertEquals("-1", DateTimeExtractAndTransform.microsecondsDiff( + epoch, new TimeStampNsLiteral("1970-01-01 00:00:00.000001999")).toSql()); + Assertions.assertEquals("1", DateTimeExtractAndTransform.secondsDiff( + new TimeStampNsLiteral("1970-01-01 00:00:01.999999999"), epoch).toSql()); + + TimeStampNsLiteral roundValue = new TimeStampNsLiteral("1970-01-01 00:00:02.123456789"); + TimeStampNsLiteral roundOrigin = new TimeStampNsLiteral("1970-01-01 00:00:00.500000000"); + Assertions.assertEquals("'1970-01-01 00:00:01.500000000'", + TimeRoundSeries.secondFloorTimeStampNs(roundValue, roundOrigin).toSql()); + Assertions.assertEquals("'1970-01-01 00:00:02.500000000'", + TimeRoundSeries.secondCeilTimeStampNs(roundValue, roundOrigin).toSql()); + TimeStampNsLiteral nanosecondRoundValue = new TimeStampNsLiteral("1970-01-01 00:00:02.000000006"); + TimeStampNsLiteral nanosecondRoundOrigin = new TimeStampNsLiteral("1970-01-01 00:00:00.000000005"); + Assertions.assertEquals("'1970-01-01 00:00:02.000000005'", + TimeRoundSeries.secondFloorTimeStampNs(nanosecondRoundValue, nanosecondRoundOrigin).toSql()); + Assertions.assertEquals("'1970-01-01 00:00:03.000000005'", + TimeRoundSeries.secondCeilTimeStampNs(nanosecondRoundValue, nanosecondRoundOrigin).toSql()); + Assertions.assertEquals("'2024-01-01 00:00:00.000000000'", + TimeRoundSeries.yearFloorTimeStampNs(normal).toSql()); + Assertions.assertEquals("'2025-01-01 00:00:00.000000000'", + TimeRoundSeries.yearCeilTimeStampNs(normal).toSql()); + Assertions.assertEquals("'2024-04-01 00:00:00.000000000'", + TimeRoundSeries.quarterCeilTimeStampNs(normal).toSql()); + Assertions.assertEquals("'2024-03-01 00:00:00.000000000'", + TimeRoundSeries.monthCeilTimeStampNs(normal).toSql()); + Assertions.assertEquals("'2024-03-01 00:00:00.000000000'", + TimeRoundSeries.dayCeilTimeStampNs(normal).toSql()); + Assertions.assertEquals("'2024-02-29 13:00:00.000000000'", + TimeRoundSeries.hourCeilTimeStampNs(normal).toSql()); + Assertions.assertEquals("'2024-02-29 12:35:00.000000000'", + TimeRoundSeries.minuteCeilTimeStampNs(normal).toSql()); + + Assertions.assertThrows(AnalysisException.class, + () -> DateTimeArithmetic.microSecondsSub(TimeStampNsLiteral.getMinValue(), new BigIntLiteral(1))); + Assertions.assertThrows(AnalysisException.class, + () -> DateTimeArithmetic.secondsAdd(TimeStampNsLiteral.getMaxValue(), new BigIntLiteral(1))); + Assertions.assertThrows(AnalysisException.class, + () -> TimeRoundSeries.secondFloorTimeStampNs(TimeStampNsLiteral.getMinValue())); } @Test @@ -1322,6 +1401,8 @@ void testDateDiff() { DateV2Literal dateV2Literal1 = new DateV2Literal("2006-12-31"); DateTimeV2Literal dateTimeV2Literal1 = new DateTimeV2Literal("2006-12-31 01:00:01"); + TimeStampNsLiteral timeStampNsLiteral = new TimeStampNsLiteral("2001-12-31 23:59:59.999999999"); + TimeStampNsLiteral timeStampNsLiteral1 = new TimeStampNsLiteral("2006-12-31 00:00:00.000000000"); Assertions.assertEquals(DateTimeArithmetic.dateDiff(dateV2Literal, dateV2Literal1).toSql(), "-1826"); Assertions.assertEquals(DateTimeArithmetic.dateDiff(dateV2Literal1, dateV2Literal).toSql(), "1826"); @@ -1331,6 +1412,8 @@ void testDateDiff() { Assertions.assertEquals(DateTimeArithmetic.dateDiff(dateV2Literal1, dateTimeV2Literal).toSql(), "1826"); Assertions.assertEquals(DateTimeArithmetic.dateDiff(dateTimeV2Literal, dateTimeV2Literal1).toSql(), "-1826"); Assertions.assertEquals(DateTimeArithmetic.dateDiff(dateTimeV2Literal1, dateTimeV2Literal).toSql(), "1826"); + Assertions.assertEquals(DateTimeArithmetic.dateDiff(timeStampNsLiteral, timeStampNsLiteral1).toSql(), "-1826"); + Assertions.assertEquals(DateTimeArithmetic.dateDiff(timeStampNsLiteral1, timeStampNsLiteral).toSql(), "1826"); DateV2Literal zeroDateV2Literal = new DateV2Literal("0000-01-01"); DateTimeV2Literal zeroDateTimeV2Literal = new DateTimeV2Literal("0000-01-01 00:00:00"); diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/check/CheckCastTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/check/CheckCastTest.java index c0bf68cedbf82e..2179b2d9ecb385 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/check/CheckCastTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/check/CheckCastTest.java @@ -17,11 +17,13 @@ package org.apache.doris.nereids.rules.expression.check; +import org.apache.doris.nereids.types.AggStateType; import org.apache.doris.nereids.types.ArrayType; import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.BitmapType; import org.apache.doris.nereids.types.BooleanType; import org.apache.doris.nereids.types.CharType; +import org.apache.doris.nereids.types.DataType; import org.apache.doris.nereids.types.DateTimeType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateType; @@ -37,13 +39,17 @@ import org.apache.doris.nereids.types.JsonType; import org.apache.doris.nereids.types.LargeIntType; import org.apache.doris.nereids.types.MapType; +import org.apache.doris.nereids.types.NullType; import org.apache.doris.nereids.types.QuantileStateType; import org.apache.doris.nereids.types.SmallIntType; import org.apache.doris.nereids.types.StringType; import org.apache.doris.nereids.types.StructField; import org.apache.doris.nereids.types.StructType; +import org.apache.doris.nereids.types.TimeStampNsType; +import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.TimeV2Type; import org.apache.doris.nereids.types.TinyIntType; +import org.apache.doris.nereids.types.VarBinaryType; import org.apache.doris.nereids.types.VarcharType; import org.apache.doris.nereids.types.VariantType; @@ -55,6 +61,65 @@ import java.util.List; public class CheckCastTest { + @Test + public void testTimeStampNsCastMatrix() { + AggStateType aggStateType = new AggStateType("max", + Collections.singletonList(TimeStampNsType.INSTANCE), + Collections.singletonList(true), true); + List strictTargets = Lists.newArrayList( + BigIntType.INSTANCE, LargeIntType.INSTANCE, + DateType.INSTANCE, DateV2Type.INSTANCE, DateTimeType.INSTANCE, + DateTimeV2Type.MAX, TimeStampNsType.INSTANCE, TimeV2Type.MAX, + CharType.SYSTEM_DEFAULT, VarcharType.SYSTEM_DEFAULT, StringType.INSTANCE, + VariantType.INSTANCE, TimeStampTzType.MAX); + for (DataType target : strictTargets) { + Assertions.assertTrue(CheckCast.check(TimeStampNsType.INSTANCE, target, true), target.toSql()); + Assertions.assertTrue(CheckCast.check(TimeStampNsType.INSTANCE, target, false), target.toSql()); + } + + Assertions.assertFalse(CheckCast.check(TimeStampNsType.INSTANCE, FloatType.INSTANCE, true)); + Assertions.assertFalse(CheckCast.check(TimeStampNsType.INSTANCE, DoubleType.INSTANCE, true)); + Assertions.assertTrue(CheckCast.check(TimeStampNsType.INSTANCE, FloatType.INSTANCE, false)); + Assertions.assertTrue(CheckCast.check(TimeStampNsType.INSTANCE, DoubleType.INSTANCE, false)); + + List unsupportedTargets = Lists.newArrayList( + BooleanType.INSTANCE, TinyIntType.INSTANCE, SmallIntType.INSTANCE, + IntegerType.INSTANCE, DecimalV2Type.SYSTEM_DEFAULT, DecimalV3Type.SYSTEM_DEFAULT, + IPv4Type.INSTANCE, IPv6Type.INSTANCE, JsonType.INSTANCE, + ArrayType.SYSTEM_DEFAULT, MapType.SYSTEM_DEFAULT, StructType.SYSTEM_DEFAULT, + HllType.INSTANCE, BitmapType.INSTANCE, QuantileStateType.INSTANCE, + VarBinaryType.INSTANCE, aggStateType); + for (DataType target : unsupportedTargets) { + Assertions.assertFalse(CheckCast.check(TimeStampNsType.INSTANCE, target, true), target.toSql()); + Assertions.assertFalse(CheckCast.check(TimeStampNsType.INSTANCE, target, false), target.toSql()); + } + + List strictSources = Lists.newArrayList( + TinyIntType.INSTANCE, SmallIntType.INSTANCE, IntegerType.INSTANCE, + BigIntType.INSTANCE, LargeIntType.INSTANCE, FloatType.INSTANCE, DoubleType.INSTANCE, + DecimalV2Type.SYSTEM_DEFAULT, DecimalV3Type.SYSTEM_DEFAULT, + DateType.INSTANCE, DateV2Type.INSTANCE, DateTimeType.INSTANCE, DateTimeV2Type.MAX, + TimeV2Type.MAX, CharType.SYSTEM_DEFAULT, VarcharType.SYSTEM_DEFAULT, + StringType.INSTANCE, TimeStampTzType.MAX, VariantType.INSTANCE); + for (DataType source : strictSources) { + Assertions.assertTrue(CheckCast.check(source, TimeStampNsType.INSTANCE, true), source.toSql()); + Assertions.assertTrue(CheckCast.check(source, TimeStampNsType.INSTANCE, false), source.toSql()); + } + + List unsupportedSources = Lists.newArrayList( + BooleanType.INSTANCE, IPv4Type.INSTANCE, IPv6Type.INSTANCE, JsonType.INSTANCE, + ArrayType.SYSTEM_DEFAULT, MapType.SYSTEM_DEFAULT, StructType.SYSTEM_DEFAULT, + HllType.INSTANCE, BitmapType.INSTANCE, QuantileStateType.INSTANCE, + VarBinaryType.INSTANCE, aggStateType); + for (DataType source : unsupportedSources) { + Assertions.assertFalse(CheckCast.check(source, TimeStampNsType.INSTANCE, true), source.toSql()); + Assertions.assertFalse(CheckCast.check(source, TimeStampNsType.INSTANCE, false), source.toSql()); + } + + Assertions.assertTrue(CheckCast.check(NullType.INSTANCE, TimeStampNsType.INSTANCE, true)); + Assertions.assertTrue(CheckCast.check(NullType.INSTANCE, TimeStampNsType.INSTANCE, false)); + } + @Test public void testCastBetweenVariantTypes() { VariantType v1Source = new VariantType(100); diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/DateFunctionRewriteTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/DateFunctionRewriteTest.java new file mode 100644 index 00000000000000..721414f0f7071c --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/DateFunctionRewriteTest.java @@ -0,0 +1,84 @@ +// 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. + +package org.apache.doris.nereids.rules.expression.rules; + +import org.apache.doris.nereids.rules.expression.ExpressionRewriteTestHelper; +import org.apache.doris.nereids.rules.expression.ExpressionRuleExecutor; +import org.apache.doris.nereids.trees.expressions.And; +import org.apache.doris.nereids.trees.expressions.EqualTo; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.GreaterThan; +import org.apache.doris.nereids.trees.expressions.GreaterThanEqual; +import org.apache.doris.nereids.trees.expressions.LessThan; +import org.apache.doris.nereids.trees.expressions.LessThanEqual; +import org.apache.doris.nereids.trees.expressions.SlotReference; +import org.apache.doris.nereids.trees.expressions.functions.scalar.Date; +import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; +import org.apache.doris.nereids.types.TimeStampNsType; +import org.apache.doris.nereids.util.ExpressionUtils; + +import com.google.common.collect.ImmutableList; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class DateFunctionRewriteTest extends ExpressionRewriteTestHelper { + private Expression timestampNs; + + @BeforeEach + void setUp() { + executor = new ExpressionRuleExecutor(ImmutableList.of( + bottomUp(DateFunctionRewrite.INSTANCE) + )); + timestampNs = new SlotReference("timestampNs", TimeStampNsType.INSTANCE, true); + } + + @Test + void testRewriteTimeStampNsDateComparisons() { + Date dateFunction = new Date(timestampNs); + DateV2Literal date = new DateV2Literal("2024-01-02"); + TimeStampNsLiteral start = new TimeStampNsLiteral("2024-01-02 00:00:00.000000000"); + TimeStampNsLiteral end = new TimeStampNsLiteral("2024-01-02 23:59:59.999999999"); + + assertRewrite(new EqualTo(dateFunction, date), new And( + new GreaterThanEqual(timestampNs, start), new LessThanEqual(timestampNs, end))); + assertRewrite(new GreaterThan(dateFunction, date), new GreaterThan(timestampNs, end)); + assertRewrite(new GreaterThanEqual(dateFunction, date), new GreaterThanEqual(timestampNs, start)); + assertRewrite(new LessThan(dateFunction, date), new LessThan(timestampNs, start)); + assertRewrite(new LessThanEqual(dateFunction, date), new LessThanEqual(timestampNs, end)); + } + + @Test + void testRewriteTimeStampNsDateComparisonsAtTypeBounds() { + Date dateFunction = new Date(timestampNs); + DateV2Literal minDate = new DateV2Literal("1677-09-21"); + DateV2Literal maxDate = new DateV2Literal("2262-04-11"); + + assertRewrite(new GreaterThanEqual(dateFunction, minDate), + new GreaterThanEqual(timestampNs, TimeStampNsLiteral.getMinValue())); + assertRewrite(new LessThanEqual(dateFunction, maxDate), + new LessThanEqual(timestampNs, TimeStampNsLiteral.getMaxValue())); + + DateV2Literal beforeMin = new DateV2Literal("1677-09-20"); + DateV2Literal afterMax = new DateV2Literal("2262-04-12"); + assertRewrite(new LessThan(dateFunction, beforeMin), ExpressionUtils.falseOrNull(timestampNs)); + assertRewrite(new GreaterThan(dateFunction, afterMax), ExpressionUtils.falseOrNull(timestampNs)); + assertRewrite(new GreaterThanEqual(dateFunction, beforeMin), ExpressionUtils.trueOrNull(timestampNs)); + assertRewrite(new LessThanEqual(dateFunction, afterMax), ExpressionUtils.trueOrNull(timestampNs)); + } +} diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/PredicateRewriteForPartitionPruneTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/PredicateRewriteForPartitionPruneTest.java new file mode 100644 index 00000000000000..e7f6f4a5a13a9c --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/PredicateRewriteForPartitionPruneTest.java @@ -0,0 +1,77 @@ +// 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. + +package org.apache.doris.nereids.rules.expression.rules; + +import org.apache.doris.nereids.trees.expressions.And; +import org.apache.doris.nereids.trees.expressions.EqualTo; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.GreaterThanEqual; +import org.apache.doris.nereids.trees.expressions.InPredicate; +import org.apache.doris.nereids.trees.expressions.LessThanEqual; +import org.apache.doris.nereids.trees.expressions.SlotReference; +import org.apache.doris.nereids.trees.expressions.functions.scalar.Date; +import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; +import org.apache.doris.nereids.types.TimeStampNsType; +import org.apache.doris.nereids.util.ExpressionUtils; + +import com.google.common.collect.ImmutableList; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class PredicateRewriteForPartitionPruneTest { + + @Test + void testRewriteTimeStampNsDateInPredicateWithExactBounds() { + SlotReference slot = new SlotReference("ts", TimeStampNsType.INSTANCE, true); + DateV2Literal minDate = new DateV2Literal("1677-09-21"); + DateV2Literal normalDate = new DateV2Literal("1970-01-01"); + DateV2Literal maxDate = new DateV2Literal("2262-04-11"); + + Expression rewritten = PredicateRewriteForPartitionPrune.rewrite( + new InPredicate(new Date(slot), ImmutableList.of(minDate, normalDate, maxDate)), null); + + Expression expected = ExpressionUtils.or(ImmutableList.of( + new And(new GreaterThanEqual(slot, TimeStampNsLiteral.getMinValue()), + new LessThanEqual(slot, + new TimeStampNsLiteral("1677-09-21 23:59:59.999999999"))), + new And(new GreaterThanEqual(slot, + new TimeStampNsLiteral("1970-01-01 00:00:00.000000000")), + new LessThanEqual(slot, + new TimeStampNsLiteral("1970-01-01 23:59:59.999999999"))), + new And(new GreaterThanEqual(slot, + new TimeStampNsLiteral("2262-04-11 00:00:00.000000000")), + new LessThanEqual(slot, TimeStampNsLiteral.getMaxValue())))); + Assertions.assertEquals(expected, rewritten); + } + + @Test + void testRewriteTimeStampNsDateEqualityAfterSingletonInSimplification() { + SlotReference slot = new SlotReference("ts", TimeStampNsType.INSTANCE, true); + + Expression rewritten = PredicateRewriteForPartitionPrune.rewrite( + new EqualTo(new Date(slot), new DateV2Literal("1969-12-31")), null); + + Expression expected = new And( + new GreaterThanEqual(slot, + new TimeStampNsLiteral("1969-12-31 00:00:00.000000000")), + new LessThanEqual(slot, + new TimeStampNsLiteral("1969-12-31 23:59:59.999999999"))); + Assertions.assertEquals(expected, rewritten); + } +} diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/SimplifyCastRuleTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/SimplifyCastRuleTest.java index 0daf90ca5abf65..36281d7b75a5af 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/SimplifyCastRuleTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/SimplifyCastRuleTest.java @@ -22,6 +22,7 @@ import org.apache.doris.nereids.rules.expression.ExpressionRuleExecutor; import org.apache.doris.nereids.trees.expressions.Cast; import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.SlotReference; import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral; import org.apache.doris.nereids.trees.expressions.literal.CharLiteral; import org.apache.doris.nereids.trees.expressions.literal.DecimalLiteral; @@ -37,6 +38,7 @@ import org.apache.doris.nereids.types.IntegerType; import org.apache.doris.nereids.types.SmallIntType; import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TinyIntType; import org.apache.doris.nereids.types.VarcharType; @@ -67,6 +69,9 @@ public void testSimplify() { Expression tinyIntLiteral = new TinyIntLiteral((byte) 12); // cast tinyint as tinyint assertRewrite(new Cast(tinyIntLiteral, TinyIntType.INSTANCE), tinyIntLiteral); + + Expression timestampNs = new SlotReference("timestamp_ns", TimeStampNsType.INSTANCE, true); + assertRewrite(new Cast(timestampNs, TimeStampNsType.INSTANCE), timestampNs); // cast tinyint as decimalv2(3,0) assertRewrite(new Cast(tinyIntLiteral, DecimalV2Type.forType(TinyIntType.INSTANCE)), new DecimalLiteral(DecimalV2Type.forType(TinyIntType.INSTANCE), new BigDecimal(12))); diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicateTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicateTest.java index 7d6967e6b3bd10..f2d97452d48bee 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicateTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rules/SimplifyComparisonPredicateTest.java @@ -46,6 +46,7 @@ import org.apache.doris.nereids.trees.expressions.literal.LargeIntLiteral; import org.apache.doris.nereids.trees.expressions.literal.NullLiteral; import org.apache.doris.nereids.trees.expressions.literal.SmallIntLiteral; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral; import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.BooleanType; @@ -60,6 +61,7 @@ import org.apache.doris.nereids.types.IntegerType; import org.apache.doris.nereids.types.LargeIntType; import org.apache.doris.nereids.types.SmallIntType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TinyIntType; import org.apache.doris.nereids.util.ExpressionUtils; @@ -460,6 +462,145 @@ void testDateTimeV2CmpDateTimeV2() { ExpressionUtils.falseOrNull(datetime2)); } + @Test + void testTimeStampNsBoundaryDateComparison() { + executor = new ExpressionRuleExecutor(ImmutableList.of( + bottomUp(SimplifyComparisonPredicate.INSTANCE) + )); + + Expression datetime9 = new SlotReference("timestampNs", TimeStampNsType.INSTANCE, true); + Expression castToDate = new Cast(datetime9, DateV2Type.INSTANCE); + DateV2Literal minDate = new DateV2Literal("1677-09-21"); + DateV2Literal maxDate = new DateV2Literal("2262-04-11"); + TimeStampNsLiteral minValue = TimeStampNsLiteral.getMinValue(); + TimeStampNsLiteral maxValue = TimeStampNsLiteral.getMaxValue(); + TimeStampNsLiteral minDayEnd = new TimeStampNsLiteral("1677-09-21 23:59:59.999999999"); + TimeStampNsLiteral maxDayStart = new TimeStampNsLiteral("2262-04-11 00:00:00.000000000"); + + assertRewrite(new EqualTo(castToDate, minDate), new And( + new GreaterThanEqual(datetime9, minValue), new LessThanEqual(datetime9, minDayEnd))); + assertRewrite(new EqualTo(castToDate, maxDate), new And( + new GreaterThanEqual(datetime9, maxDayStart), new LessThanEqual(datetime9, maxValue))); + assertRewrite(new GreaterThanEqual(castToDate, minDate), new GreaterThanEqual(datetime9, minValue)); + assertRewrite(new LessThan(castToDate, minDate), new LessThan(datetime9, minValue)); + assertRewrite(new GreaterThan(castToDate, maxDate), new GreaterThan(datetime9, maxValue)); + assertRewrite(new LessThanEqual(castToDate, maxDate), new LessThanEqual(datetime9, maxValue)); + + DateV2Literal beforeMinDate = new DateV2Literal("1677-09-20"); + DateV2Literal afterMaxDate = new DateV2Literal("2262-04-12"); + assertRewrite(new EqualTo(castToDate, beforeMinDate), ExpressionUtils.falseOrNull(datetime9)); + assertRewrite(new GreaterThan(castToDate, beforeMinDate), ExpressionUtils.trueOrNull(datetime9)); + assertRewrite(new EqualTo(castToDate, afterMaxDate), ExpressionUtils.falseOrNull(datetime9)); + assertRewrite(new LessThan(castToDate, afterMaxDate), ExpressionUtils.trueOrNull(datetime9)); + } + + @Test + void testDateTimeToTimeStampNsComparison() { + executor = new ExpressionRuleExecutor(ImmutableList.of( + bottomUp(SimplifyComparisonPredicate.INSTANCE) + )); + + Expression datetimeV2 = new SlotReference("datetimeV2", DateTimeV2Type.of(6), true); + Expression castToTimestampNs = new Cast(datetimeV2, TimeStampNsType.INSTANCE); + TimeStampNsLiteral exact = new TimeStampNsLiteral("2024-01-02 03:04:05.123456000"); + TimeStampNsLiteral inexact = new TimeStampNsLiteral("2024-01-02 03:04:05.123456789"); + DateTimeV2Literal floor = new DateTimeV2Literal( + DateTimeV2Type.of(6), "2024-01-02 03:04:05.123456"); + DateTimeV2Literal ceiling = new DateTimeV2Literal( + DateTimeV2Type.of(6), "2024-01-02 03:04:05.123457"); + + assertRewrite(new EqualTo(castToTimestampNs, exact), new EqualTo(datetimeV2, floor)); + assertRewrite(new EqualTo(castToTimestampNs, inexact), ExpressionUtils.falseOrNull(datetimeV2)); + assertRewrite(new NullSafeEqual(castToTimestampNs, inexact), BooleanLiteral.FALSE); + assertRewrite(new GreaterThan(castToTimestampNs, inexact), new GreaterThan(datetimeV2, floor)); + assertRewrite(new LessThanEqual(castToTimestampNs, inexact), new LessThanEqual(datetimeV2, floor)); + assertRewrite(new LessThan(castToTimestampNs, inexact), new LessThan(datetimeV2, ceiling)); + assertRewrite(new GreaterThanEqual(castToTimestampNs, inexact), + new GreaterThanEqual(datetimeV2, ceiling)); + + Expression datetime = new SlotReference("datetime", DateTimeType.INSTANCE, true); + Expression castDatetimeToTimestampNs = new Cast(datetime, TimeStampNsType.INSTANCE); + TimeStampNsLiteral subsecond = new TimeStampNsLiteral("2024-01-02 03:04:05.000000001"); + assertRewrite(new GreaterThan(castDatetimeToTimestampNs, subsecond), + new GreaterThan(datetime, new DateTimeLiteral("2024-01-02 03:04:05"))); + assertRewrite(new LessThan(castDatetimeToTimestampNs, subsecond), + new LessThan(datetime, new DateTimeLiteral("2024-01-02 03:04:06"))); + + Expression timestampNs = new SlotReference("timestampNs", TimeStampNsType.INSTANCE, true); + Expression noOpCast = new Cast(timestampNs, TimeStampNsType.INSTANCE); + EqualTo noOpComparison = new EqualTo(noOpCast, exact); + assertRewrite(noOpComparison, noOpComparison); + } + + @Test + void testTimeStampNsDateComparisonOperatorsAndOutsideRange() { + executor = new ExpressionRuleExecutor(ImmutableList.of( + bottomUp(SimplifyComparisonPredicate.INSTANCE) + )); + + Expression timestampNs = new SlotReference("timestampNs", TimeStampNsType.INSTANCE, true); + Expression castToDate = new Cast(timestampNs, DateV2Type.INSTANCE); + DateV2Literal date = new DateV2Literal("2024-01-02"); + TimeStampNsLiteral start = new TimeStampNsLiteral("2024-01-02 00:00:00.000000000"); + TimeStampNsLiteral end = new TimeStampNsLiteral("2024-01-02 23:59:59.999999999"); + + assertRewrite(new GreaterThanEqual(castToDate, date), new GreaterThanEqual(timestampNs, start)); + assertRewrite(new LessThan(castToDate, date), new LessThan(timestampNs, start)); + assertRewrite(new GreaterThan(castToDate, date), new GreaterThan(timestampNs, end)); + assertRewrite(new LessThanEqual(castToDate, date), new LessThanEqual(timestampNs, end)); + assertRewrite(new EqualTo(castToDate, date), new And( + new GreaterThanEqual(timestampNs, start), new LessThanEqual(timestampNs, end))); + assertRewrite(new NullSafeEqual(castToDate, date), new And(ImmutableList.of( + new GreaterThanEqual(timestampNs, start), + new LessThanEqual(timestampNs, end), + new Not(new IsNull(timestampNs))))); + + DateV2Literal beforeMin = new DateV2Literal("1677-09-20"); + assertRewrite(new NullSafeEqual(castToDate, beforeMin), BooleanLiteral.FALSE); + assertRewrite(new GreaterThanEqual(castToDate, beforeMin), ExpressionUtils.trueOrNull(timestampNs)); + assertRewrite(new LessThan(castToDate, beforeMin), ExpressionUtils.falseOrNull(timestampNs)); + assertRewrite(new LessThanEqual(castToDate, beforeMin), ExpressionUtils.falseOrNull(timestampNs)); + + DateV2Literal afterMax = new DateV2Literal("2262-04-12"); + assertRewrite(new NullSafeEqual(castToDate, afterMax), BooleanLiteral.FALSE); + assertRewrite(new LessThanEqual(castToDate, afterMax), ExpressionUtils.trueOrNull(timestampNs)); + assertRewrite(new GreaterThan(castToDate, afterMax), ExpressionUtils.falseOrNull(timestampNs)); + assertRewrite(new GreaterThanEqual(castToDate, afterMax), ExpressionUtils.falseOrNull(timestampNs)); + } + + @Test + void testDateToTimeStampNsSubMicrosecondComparison() { + executor = new ExpressionRuleExecutor(ImmutableList.of( + bottomUp(SimplifyComparisonPredicate.INSTANCE) + )); + + Expression date = new SlotReference("date", DateV2Type.INSTANCE, true); + Expression castToNano = new Cast(date, TimeStampNsType.INSTANCE); + TimeStampNsLiteral nanoAfterMidnight = new TimeStampNsLiteral( + "2024-01-01 00:00:00.000000001"); + DateV2Literal currentDate = new DateV2Literal("2024-01-01"); + DateV2Literal nextDate = new DateV2Literal("2024-01-02"); + + assertRewrite(new EqualTo(castToNano, nanoAfterMidnight), ExpressionUtils.falseOrNull(date)); + assertRewrite(new EqualTo(nanoAfterMidnight, castToNano), ExpressionUtils.falseOrNull(date)); + assertRewrite(new NullSafeEqual(castToNano, nanoAfterMidnight), BooleanLiteral.FALSE); + assertRewrite(new NullSafeEqual(nanoAfterMidnight, castToNano), BooleanLiteral.FALSE); + + assertRewrite(new LessThan(castToNano, nanoAfterMidnight), new LessThan(date, nextDate)); + assertRewrite(new LessThan(nanoAfterMidnight, castToNano), new GreaterThan(date, currentDate)); + assertRewrite(new LessThanEqual(castToNano, nanoAfterMidnight), new LessThanEqual(date, currentDate)); + assertRewrite(new LessThanEqual(nanoAfterMidnight, castToNano), new GreaterThanEqual(date, nextDate)); + assertRewrite(new GreaterThan(castToNano, nanoAfterMidnight), new GreaterThan(date, currentDate)); + assertRewrite(new GreaterThan(nanoAfterMidnight, castToNano), new LessThan(date, nextDate)); + assertRewrite(new GreaterThanEqual(castToNano, nanoAfterMidnight), new GreaterThanEqual(date, nextDate)); + assertRewrite(new GreaterThanEqual(nanoAfterMidnight, castToNano), new LessThanEqual(date, currentDate)); + + assertRewrite(new Not(new EqualTo(castToNano, nanoAfterMidnight)), + new Not(ExpressionUtils.falseOrNull(date))); + assertRewrite(new Not(new EqualTo(nanoAfterMidnight, castToNano)), + new Not(ExpressionUtils.falseOrNull(date))); + } + @Test void testRound() { executor = new ExpressionRuleExecutor(ImmutableList.of( diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/InferPredicateByReplaceTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/InferPredicateByReplaceTest.java index ad35028d7b9467..87f88157a0f348 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/InferPredicateByReplaceTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/InferPredicateByReplaceTest.java @@ -29,16 +29,20 @@ import org.apache.doris.nereids.trees.expressions.SlotReference; import org.apache.doris.nereids.trees.expressions.functions.scalar.Abs; import org.apache.doris.nereids.trees.expressions.functions.scalar.DateTrunc; +import org.apache.doris.nereids.trees.expressions.literal.DateTimeLiteral; import org.apache.doris.nereids.trees.expressions.literal.DateTimeV2Literal; import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral; import org.apache.doris.nereids.trees.expressions.literal.StringLiteral; import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral; import org.apache.doris.nereids.types.BigIntType; +import org.apache.doris.nereids.types.DateTimeType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateType; import org.apache.doris.nereids.types.IntegerType; import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TinyIntType; +import org.apache.doris.nereids.util.PredicateInferUtils; import com.google.common.collect.ImmutableList; import org.junit.jupiter.api.Assertions; @@ -186,6 +190,21 @@ public void testValidForInfer() { Assertions.assertEquals(2, InferPredicateByReplace.infer(inputs).size()); } + @Test + public void testTimestampNsCastIsNotRemovedForPredicateInference() { + SlotReference timestampNs = new SlotReference("timestamp_ns", TimeStampNsType.INSTANCE); + Cast roundedToMicroseconds = new Cast(timestampNs, DateTimeV2Type.of(6)); + EqualTo equalTo = new EqualTo( + roundedToMicroseconds, new DateTimeV2Literal("2024-01-01 00:00:00.123457")); + + Assertions.assertFalse(PredicateInferUtils.getPairFromCast(equalTo).isPresent()); + + Cast roundedToSeconds = new Cast(timestampNs, DateTimeType.INSTANCE); + EqualTo legacyEqualTo = new EqualTo( + roundedToSeconds, new DateTimeLiteral("2024-01-01 00:00:00")); + Assertions.assertFalse(PredicateInferUtils.getPairFromCast(legacyEqualTo).isPresent()); + } + @Test public void testNotInferWithTransitiveEqualitySameTable() { // a = b, b = c diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/PushDownVirtualColumnsIntoOlapScanTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/PushDownVirtualColumnsIntoOlapScanTest.java index db7db44de31620..64a4cee5920bf7 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/PushDownVirtualColumnsIntoOlapScanTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/PushDownVirtualColumnsIntoOlapScanTest.java @@ -55,6 +55,7 @@ import org.apache.doris.nereids.trees.plans.logical.LogicalProject; import org.apache.doris.nereids.types.DataType; import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.VarcharType; import org.apache.doris.nereids.util.MemoPatternMatchSupported; import org.apache.doris.nereids.util.MemoTestUtils; @@ -81,6 +82,17 @@ */ public class PushDownVirtualColumnsIntoOlapScanTest implements MemoPatternMatchSupported { + @Test + void testTimeStampNsVirtualColumnTypeIsSupported() throws Exception { + PushDownVirtualColumnsIntoOlapScan rule = new PushDownVirtualColumnsIntoOlapScan(); + Method typeCheckMethod = rule.getClass() + .getDeclaredMethod("isSupportedVirtualColumnType", Expression.class); + typeCheckMethod.setAccessible(true); + + SlotReference timestampNs = new SlotReference("ts", TimeStampNsType.INSTANCE, true); + Assertions.assertTrue((boolean) typeCheckMethod.invoke(rule, timestampNs)); + } + @Test public void testExtractRepeatedSubExpressions() { ConnectContext connectContext = MemoTestUtils.createConnectContext(); diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/stats/FilterEstimationTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/stats/FilterEstimationTest.java index 8533adb3061ad3..033ba1c8fc4938 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/stats/FilterEstimationTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/stats/FilterEstimationTest.java @@ -1406,6 +1406,34 @@ public void testStringRangeColToDateLiteral() { Assertions.assertEquals(4.24, filter2021.getRowCount(), 0.01); } + @Test + public void testStringRangeColToTimeStampNsLiteral() { + SlotReference timestamp = new SlotReference("timestamp", new VarcharType(30)); + ColumnStatistic timestampStats = new ColumnStatisticBuilder(100) + .setNdv(100) + .setAvgSizeByte(30) + .setNumNulls(0) + .setMaxExpr(new StringLiteral( + "2020-2-01 00:00:00.000000002").toLegacyLiteral()) + .setMaxValue(new VarcharLiteral( + "2020-2-01 00:00:00.000000002").getDouble()) + .setMinExpr(new StringLiteral( + "2020-1-01 00:00:00.000000001").toLegacyLiteral()) + .setMinValue(new VarcharLiteral( + "2020-1-01 00:00:00.000000001").getDouble()) + .build(); + Statistics baseStats = new StatisticsBuilder() + .setRowCount(100) + .putColumnStatistics(timestamp, timestampStats) + .build(); + + VarcharLiteral october = new VarcharLiteral("2020-10-01 00:00:00.000000003"); + Statistics result = new FilterEstimation().estimate( + new LessThan(timestamp, october), baseStats); + + Assertions.assertEquals(100, result.getRowCount()); + } + @Test public void testStringRangeColToCol() { SlotReference a = new SlotReference("a", new VarcharType(25)); diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/CastTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/CastTest.java index c66203b673f292..ad7f8f3d28f599 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/CastTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/CastTest.java @@ -17,6 +17,7 @@ package org.apache.doris.nereids.trees.expressions; +import org.apache.doris.nereids.trees.expressions.literal.DateLiteral; import org.apache.doris.nereids.types.ArrayType; import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.BooleanType; @@ -36,6 +37,8 @@ import org.apache.doris.nereids.types.LargeIntType; import org.apache.doris.nereids.types.SmallIntType; import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.TimeStampNsType; +import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.TimeV2Type; import org.apache.doris.nereids.types.TinyIntType; import org.apache.doris.nereids.types.VarcharType; @@ -656,6 +659,37 @@ public void testIdentityDateTimeV2CastKeepsRequiredness() { Assertions.assertFalse(Cast.castNullable(false, dateTimeV2, dateTimeV2)); } + @Test + public void testTimeStampNsCastNullability() { + Assertions.assertTrue(Cast.castNullable(false, DateType.INSTANCE, TimeStampNsType.INSTANCE)); + Assertions.assertTrue(Cast.castNullable(false, DateV2Type.INSTANCE, TimeStampNsType.INSTANCE)); + Assertions.assertTrue(Cast.castNullable(false, DateTimeType.INSTANCE, TimeStampNsType.INSTANCE)); + Assertions.assertTrue(Cast.castNullable(false, DateTimeV2Type.MAX, TimeStampNsType.INSTANCE)); + Assertions.assertTrue(Cast.castNullable(false, TimeStampTzType.MAX, TimeStampNsType.INSTANCE)); + Assertions.assertTrue(Cast.castNullable(false, TimeV2Type.MAX, TimeStampNsType.INSTANCE)); + Assertions.assertFalse(Cast.castNullable(false, TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE)); + Assertions.assertFalse(Cast.castNullable(false, TimeStampNsType.INSTANCE, DateTimeV2Type.MAX)); + Assertions.assertTrue(Cast.castNullable(false, TimeStampNsType.INSTANCE, TimeStampTzType.MAX)); + } + + @Test + public void testCastToTimeStampNsMonotonicRange() { + SlotReference date = new SlotReference("date", DateType.INSTANCE, false); + Cast timestampNsCast = new Cast(date, TimeStampNsType.INSTANCE); + + DateLiteral insideLower = new DateLiteral(1970, 1, 1); + DateLiteral insideUpper = new DateLiteral(2024, 2, 29); + Assertions.assertTrue(timestampNsCast.isMonotonic(insideLower, insideUpper)); + Assertions.assertFalse(timestampNsCast.isMonotonic(null, insideUpper)); + Assertions.assertFalse(timestampNsCast.isMonotonic(insideLower, null)); + Assertions.assertFalse(timestampNsCast.isMonotonic(new DateLiteral(1600, 1, 1), insideUpper)); + Assertions.assertFalse(timestampNsCast.isMonotonic(insideLower, new DateLiteral(2300, 1, 1))); + + Cast datetimeV2Cast = new Cast(date, DateTimeV2Type.MAX); + Assertions.assertTrue(datetimeV2Cast.isMonotonic(null, insideUpper)); + Assertions.assertTrue(datetimeV2Cast.isMonotonic(insideLower, null)); + } + @Test public void testCastFromArray() { try (MockedStatic mockedSessionVariable = Mockito.mockStatic(SessionVariable.class)) { diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/LiteralTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/LiteralTest.java index 4964414e6b3db5..aaa63ac35624cd 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/LiteralTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/LiteralTest.java @@ -23,12 +23,15 @@ import org.apache.doris.nereids.trees.expressions.literal.Literal; import org.apache.doris.nereids.trees.expressions.literal.NullLiteral; import org.apache.doris.nereids.trees.expressions.literal.StringLiteral; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.types.ArrayType; import org.apache.doris.nereids.types.DataType; +import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.IntegerType; import org.apache.doris.nereids.types.StringType; import org.apache.doris.nereids.types.StructField; import org.apache.doris.nereids.types.StructType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.proto.Types.PGenericType; import org.apache.doris.proto.Types.PGenericType.TypeId; import org.apache.doris.proto.Types.PValues; @@ -57,6 +60,92 @@ public void testEqual() { Assertions.assertTrue(Literal.of(false) instanceof BooleanLiteral); } + @Test + public void testGetResultExpressionTimeStampNs() { + assertTimeStampNsResult(Long.MIN_VALUE, "1677-09-21 00:12:43.145224192"); + assertTimeStampNsResult(123456800L, "1970-01-01 00:00:00.123456800"); + assertTimeStampNsResult(-10L, "1969-12-31 23:59:59.999999990"); + assertTimeStampNsResult(-1L, "1969-12-31 23:59:59.999999999"); + assertTimeStampNsResult(Long.MAX_VALUE, "2262-04-11 23:47:16.854775807"); + } + + @Test + public void testGetResultExpressionNullableTimeStampNs() { + PValues values = PValues.newBuilder() + .setType(PGenericType.newBuilder().setId(TypeId.INT64).build()) + .addInt64Value(-1L) + .addInt64Value(0L) + .setHasNull(true) + .addNullMap(false) + .addNullMap(true) + .build(); + + List result = org.apache.doris.nereids.rules.expression.rules.FoldConstantRuleOnBE + .getResultExpression(TimeStampNsType.INSTANCE, values); + Assertions.assertEquals(2, result.size()); + Assertions.assertEquals("1969-12-31 23:59:59.999999999", result.get(0).getStringValue()); + Assertions.assertInstanceOf(NullLiteral.class, result.get(1)); + } + + @Test + public void testGetResultExpressionNestedTimeStampNs() { + TimeStampNsType nanoType = TimeStampNsType.INSTANCE; + PGenericType int64Type = PGenericType.newBuilder().setId(TypeId.INT64).build(); + PValues nanoValues = PValues.newBuilder() + .setType(int64Type) + .addInt64Value(-1L) + .addInt64Value(123456789L) + .build(); + PValues arrayValues = PValues.newBuilder() + .setType(PGenericType.newBuilder().setId(TypeId.LIST).build()) + .addChildElement(nanoValues) + .addChildOffset(2) + .build(); + + List result = org.apache.doris.nereids.rules.expression.rules.FoldConstantRuleOnBE + .getResultExpression(ArrayType.of(nanoType), arrayValues); + Assertions.assertEquals(1, result.size()); + Assertions.assertTrue(result.get(0) instanceof ArrayLiteral); + List items = ((ArrayLiteral) result.get(0)).getValue(); + Assertions.assertEquals("1969-12-31 23:59:59.999999999", + ((TimeStampNsLiteral) items.get(0)).getStringValue()); + Assertions.assertEquals("1970-01-01 00:00:00.123456789", + ((TimeStampNsLiteral) items.get(1)).getStringValue()); + } + + @Test + public void testGetResultExpressionDateTimeV2AlongsideTimeStampNs() { + long packedDateTime = (2024L << 46) | (1L << 42) | (2L << 37) + | (3L << 32) | (4L << 26) | (5L << 20) | 123456L; + PValues values = PValues.newBuilder() + .setType(PGenericType.newBuilder().setId(TypeId.UINT64).build()) + .addUint64Value(packedDateTime) + .addUint64Value(0) + .setHasNull(true) + .build(); + + List result = org.apache.doris.nereids.rules.expression.rules.FoldConstantRuleOnBE + .getResultExpression(DateTimeV2Type.of(6), values); + Assertions.assertEquals(2, result.size()); + Assertions.assertEquals("2024-01-02 03:04:05.123456", result.get(0).getStringValue()); + Assertions.assertInstanceOf(NullLiteral.class, result.get(1)); + } + + private void assertTimeStampNsResult(long epochNanos, String expected) { + PValues values = PValues.newBuilder() + .setType(PGenericType.newBuilder().setId(TypeId.INT64).build()) + .addInt64Value(epochNanos) + .build(); + List result = org.apache.doris.nereids.rules.expression.rules.FoldConstantRuleOnBE + .getResultExpression(TimeStampNsType.INSTANCE, values); + + Assertions.assertEquals(1, result.size()); + Assertions.assertInstanceOf(TimeStampNsLiteral.class, result.get(0)); + TimeStampNsLiteral literal = (TimeStampNsLiteral) result.get(0); + Assertions.assertSame(TimeStampNsType.INSTANCE, literal.getDataType()); + Assertions.assertEquals(expected, literal.getStringValue()); + } + @Test public void testGetResultExpressionArrayInt() { int num = 10; diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/scalar/TimestampNsFunctionSignatureTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/scalar/TimestampNsFunctionSignatureTest.java new file mode 100644 index 00000000000000..8dd36b0938c0dd --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/scalar/TimestampNsFunctionSignatureTest.java @@ -0,0 +1,251 @@ +// 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. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.parser.NereidsParser; +import org.apache.doris.nereids.rules.analysis.ExpressionAnalyzer; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.SlotReference; +import org.apache.doris.nereids.trees.expressions.functions.BoundFunction; +import org.apache.doris.nereids.trees.expressions.functions.agg.SequenceCount; +import org.apache.doris.nereids.trees.expressions.functions.agg.SequenceMatch; +import org.apache.doris.nereids.trees.expressions.functions.agg.TopNWeighted; +import org.apache.doris.nereids.trees.expressions.functions.agg.WindowFunnel; +import org.apache.doris.nereids.trees.expressions.functions.agg.WindowFunnelV2; +import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral; +import org.apache.doris.nereids.trees.expressions.literal.CharLiteral; +import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral; +import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral; +import org.apache.doris.nereids.types.ArrayType; +import org.apache.doris.nereids.types.BigIntType; +import org.apache.doris.nereids.types.BooleanType; +import org.apache.doris.nereids.types.DataType; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.DecimalV3Type; +import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.SmallIntType; +import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.TimeStampNsType; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.TimeV2Type; +import org.apache.doris.nereids.types.TinyIntType; +import org.apache.doris.nereids.types.VarcharType; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class TimestampNsFunctionSignatureTest { + + private final Expression timestampNs = SlotReference.of("timestamp_ns", TimeStampNsType.INSTANCE); + private final NereidsParser parser = new NereidsParser(); + + @Test + void testTimestampNsUsesDedicatedScalarFunctionSignatures() { + assertSignature(new WeeksAdd(timestampNs, new IntegerLiteral(1)), + TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE, IntegerType.INSTANCE); + assertSignature(new Year(timestampNs), SmallIntType.INSTANCE, TimeStampNsType.INSTANCE); + assertSignature(new Date(timestampNs), DateV2Type.INSTANCE, TimeStampNsType.INSTANCE); + assertSignature(new DateFormat(timestampNs, new VarcharLiteral("%Y-%m-%d")), + VarcharType.SYSTEM_DEFAULT, TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT); + assertSignature(new DateTrunc(timestampNs, new VarcharLiteral("day")), + TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT); + assertSignature(new UnixTimestamp(timestampNs), + DecimalV3Type.createDecimalV3Type(21, 9), TimeStampNsType.INSTANCE); + assertSignature(new WidthBucket(timestampNs, timestampNs, timestampNs, + new IntegerLiteral(1)), + BigIntType.INSTANCE, TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE, + TimeStampNsType.INSTANCE, TinyIntType.INSTANCE); + } + + @Test + void testUntypedDatetimeInputsDoNotSelectTimestampNsSignatures() { + VarcharLiteral first = new VarcharLiteral("2010-01-01 01:00:00"); + VarcharLiteral second = new VarcharLiteral("2010-01-02 01:00:00"); + assertSignature(new TimeDiff(first, second), TimeV2Type.SYSTEM_DEFAULT, + DateTimeV2Type.SYSTEM_DEFAULT, DateTimeV2Type.SYSTEM_DEFAULT); + assertSignature(new HourCeil(first, new IntegerLiteral(1), second), + DateTimeV2Type.SYSTEM_DEFAULT, DateTimeV2Type.SYSTEM_DEFAULT, + IntegerType.INSTANCE, DateTimeV2Type.SYSTEM_DEFAULT); + + CharLiteral charDate = new CharLiteral("2012-12-01", 16); + assertSignature(new DayOfWeek(charDate), TinyIntType.INSTANCE, DateV2Type.INSTANCE); + + Expression varcharColumn = SlotReference.of("varchar_column", VarcharType.SYSTEM_DEFAULT); + assertNoTimestampNsSignature(new TimeDiff(varcharColumn, varcharColumn)); + assertNoTimestampNsSignature(new Date(varcharColumn)); + assertNoTimestampNsSignature(new MonthCeil(varcharColumn)); + assertNoTimestampNsSignature( + new Date(new VarcharLiteral("170141183460469231731687303715884105727"))); + assertSignature(new DayMicrosecondAdd(new VarcharLiteral("2024-07-31"), + new VarcharLiteral("0 10:20:30.123456")), + DateTimeV2Type.MAX, DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT); + assertSignature(new SecondMicrosecondAdd(new VarcharLiteral("2025-10-29 10:10:10"), + new VarcharLiteral("1.1")), + DateTimeV2Type.MAX, DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT); + } + + @Test + void testUntypedDatetimeExpressionsKeepDateTimeV2SignaturesAfterAnalysis() { + assertAnalyzedType( + "date_add('2024-07-31', interval '0 10:20:30.123456' day_microsecond)", + DateTimeV2Type.MAX); + assertAnalyzedType( + "date_add('2025-10-29 10:10:10', interval '1.1' second_microsecond)", + DateTimeV2Type.MAX); + assertAnalyzedType("ifnull(date(substring('2020-02-09', 1, 1024)), null)", + DateV2Type.INSTANCE); + } + + @Test + void testMixedDateTimeV2DiffPromotesToTimestampNsSignature() { + Expression datetime = SlotReference.of("datetime", DateTimeV2Type.MAX); + assertSignature(new DateDiff(timestampNs, datetime), IntegerType.INSTANCE, + TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE); + assertSignature(new TimeDiff(timestampNs, datetime), TimeV2Type.MAX, + TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE); + } + + @Test + void testMixedTimestampTzFunctionsPromoteToTimestampNsSignature() { + Expression timestampTz = SlotReference.of("timestamp_tz", TimeStampTzType.MAX); + assertSignature(new DateDiff(timestampNs, timestampTz), IntegerType.INSTANCE, + TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE); + assertSignature(new TimeDiff(timestampTz, timestampNs), TimeV2Type.MAX, + TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE); + assertSignature(new SecondsDiff(timestampNs, timestampTz), BigIntType.INSTANCE, + TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE); + assertSignature(new Field(timestampTz, timestampNs), IntegerType.INSTANCE, + TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE); + } + + @Test + void testDateTimeV2AndTimestampTzFunctionsUseDateTimeV2Signature() { + Expression datetime = SlotReference.of("datetime", DateTimeV2Type.of(3)); + Expression timestampTz = SlotReference.of("timestamp_tz", TimeStampTzType.MAX); + assertSignature(new DateDiff(datetime, timestampTz), IntegerType.INSTANCE, + DateTimeV2Type.MAX, DateTimeV2Type.MAX); + assertSignature(new TimeDiff(timestampTz, datetime), TimeV2Type.MAX, + DateTimeV2Type.MAX, DateTimeV2Type.MAX); + assertSignature(new SecondsDiff(datetime, timestampTz), BigIntType.INSTANCE, + DateTimeV2Type.MAX, DateTimeV2Type.MAX); + } + + @Test + void testMixedDatetimeArgumentsNeverDemoteTimestampNs() { + Expression datetime = SlotReference.of("datetime", DateTimeV2Type.MAX); + assertSignature(new SecondFloor(timestampNs, datetime), TimeStampNsType.INSTANCE, + TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE); + assertSignature(new ArrayRange(timestampNs, datetime), + ArrayType.of(TimeStampNsType.INSTANCE), + TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE); + assertSignature(new Field(timestampNs, datetime), IntegerType.INSTANCE, + TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE); + } + + @Test + void testMicrosecondArithmeticDoesNotRewriteTimestampNsToDatetimeV2() { + VarcharLiteral interval = new VarcharLiteral("1.000001"); + assertTimestampNsBinary(new MicroSecondsAdd(timestampNs, new IntegerLiteral(1))); + assertTimestampNsBinary(new MicroSecondsSub(timestampNs, new IntegerLiteral(1))); + assertTimestampNsBinary(new MilliSecondsAdd(timestampNs, new IntegerLiteral(1))); + assertTimestampNsBinary(new MilliSecondsSub(timestampNs, new IntegerLiteral(1))); + assertTimestampNsStringBinary(new DayMicrosecondAdd(timestampNs, interval)); + assertTimestampNsStringBinary(new DayMicrosecondSub(timestampNs, interval)); + assertTimestampNsStringBinary(new HourMicrosecondAdd(timestampNs, interval)); + assertTimestampNsStringBinary(new HourMicrosecondSub(timestampNs, interval)); + assertTimestampNsStringBinary(new MinuteMicrosecondAdd(timestampNs, interval)); + assertTimestampNsStringBinary(new MinuteMicrosecondSub(timestampNs, interval)); + assertTimestampNsStringBinary(new SecondMicrosecondAdd(timestampNs, interval)); + assertTimestampNsStringBinary(new SecondMicrosecondSub(timestampNs, interval)); + } + + @Test + void testTimeAndTimeArithmeticSignatures() { + Expression time = SlotReference.of("time", TimeV2Type.MAX); + assertSignature(new Time(timestampNs), TimeV2Type.MAX, TimeStampNsType.INSTANCE); + assertSignature(new AddTime(timestampNs, time), TimeStampNsType.INSTANCE, + TimeStampNsType.INSTANCE, TimeV2Type.MAX); + assertSignature(new SubTime(timestampNs, time), TimeStampNsType.INSTANCE, + TimeStampNsType.INSTANCE, TimeV2Type.MAX); + assertSignature(new ConvertTz(timestampNs, new VarcharLiteral("+08:00"), + new VarcharLiteral("+00:00")), + TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE, + VarcharType.SYSTEM_DEFAULT, VarcharType.SYSTEM_DEFAULT); + } + + @Test + void testTimestampNsAggregateFunctionSignatures() { + Expression condition1 = SlotReference.of("condition1", BooleanType.INSTANCE); + Expression condition2 = SlotReference.of("condition2", BooleanType.INSTANCE); + Expression weight = SlotReference.of("weight", BigIntType.INSTANCE); + VarcharLiteral pattern = new VarcharLiteral("(?1)(?2)"); + VarcharLiteral mode = new VarcharLiteral("default"); + + assertSignature(new SequenceCount(pattern, timestampNs, condition1, condition2), + BigIntType.INSTANCE, StringType.INSTANCE, + TimeStampNsType.INSTANCE, BooleanType.INSTANCE, BooleanType.INSTANCE); + assertSignature(new SequenceMatch(pattern, timestampNs, condition1, condition2), + BooleanType.INSTANCE, StringType.INSTANCE, + TimeStampNsType.INSTANCE, BooleanType.INSTANCE, BooleanType.INSTANCE); + assertSignature(new WindowFunnel(new BigIntLiteral(3600), mode, + timestampNs, condition1, condition2), + IntegerType.INSTANCE, BigIntType.INSTANCE, StringType.INSTANCE, + TimeStampNsType.INSTANCE, BooleanType.INSTANCE, BooleanType.INSTANCE); + assertSignature(new WindowFunnelV2(new BigIntLiteral(3600), mode, + timestampNs, condition1, condition2), + IntegerType.INSTANCE, BigIntType.INSTANCE, StringType.INSTANCE, + TimeStampNsType.INSTANCE, BooleanType.INSTANCE, BooleanType.INSTANCE); + assertSignature(new TopNWeighted(timestampNs, weight, new IntegerLiteral(2)), + ArrayType.of(TimeStampNsType.INSTANCE), TimeStampNsType.INSTANCE, + BigIntType.INSTANCE, IntegerType.INSTANCE); + } + + private void assertTimestampNsBinary(ScalarFunction function) { + assertSignature(function, TimeStampNsType.INSTANCE, + TimeStampNsType.INSTANCE, BigIntType.INSTANCE); + } + + private void assertTimestampNsStringBinary(ScalarFunction function) { + assertSignature(function, TimeStampNsType.INSTANCE, + TimeStampNsType.INSTANCE, VarcharType.SYSTEM_DEFAULT); + } + + private void assertSignature(BoundFunction function, DataType returnType, DataType... argumentTypes) { + FunctionSignature signature = function.getSignature(); + Assertions.assertEquals(returnType, signature.returnType, function.getName()); + Assertions.assertArrayEquals(argumentTypes, signature.argumentsTypes.toArray(), function.getName()); + } + + private void assertNoTimestampNsSignature(BoundFunction function) { + FunctionSignature signature = function.getSignature(); + Assertions.assertFalse(signature.returnType.isTimeStampNsType(), function.getName()); + Assertions.assertTrue(signature.argumentsTypes.stream().noneMatch(DataType::isTimeStampNsType), + function.getName()); + } + + private void assertAnalyzedType(String sql, DataType expectedType) { + Expression analyzed = ExpressionAnalyzer.analyzeFunction(null, null, parser.parseExpression(sql)); + String details = analyzed instanceof BoundFunction + ? sql + ": " + analyzed + ", signature=" + ((BoundFunction) analyzed).getSignature() + : sql + ": " + analyzed; + Assertions.assertEquals(expectedType, analyzed.getDataType(), details); + Assertions.assertTrue(analyzed.checkInputDataTypes().success(), sql); + } +} diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteralTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteralTest.java index 8b2db5b3511e8b..cfab3869e2723d 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteralTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteralTest.java @@ -30,6 +30,7 @@ import org.apache.doris.nereids.types.LargeIntType; import org.apache.doris.nereids.types.SmallIntType; import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; @@ -224,6 +225,55 @@ void testPoint() { new DateTimeV2Literal("2020.02.01 00.00.00.0000001"); } + @Test + void testTimeStampNsseconds() { + Assertions.assertFalse(DateTimeLiteral.class.isAssignableFrom(TimeStampNsLiteral.class)); + TimeStampNsLiteral nanoseconds = + new TimeStampNsLiteral("1970-01-01 00:00:00.123456789"); + Assertions.assertEquals(TimeStampNsType.INSTANCE, nanoseconds.getDataType()); + Assertions.assertEquals(123456789, nanoseconds.getNanoSecond()); + Assertions.assertEquals("1970-01-01 00:00:00.123456789", + nanoseconds.getStringValue()); + Assertions.assertEquals("1970-01-01 00:00:00.123456789", + nanoseconds.toLegacyLiteral().getStringValue()); + Assertions.assertInstanceOf(org.apache.doris.analysis.TimeStampNsLiteral.class, + nanoseconds.toLegacyLiteral()); + + TimeStampNsLiteral rounded = new TimeStampNsLiteral("1970-01-01 00:00:00.12345675"); + Assertions.assertEquals("1970-01-01 00:00:00.123456750", + rounded.getStringValue()); + + TimeStampNsLiteral scale7 = new TimeStampNsLiteral("1969-12-31 23:59:59.99999994"); + Assertions.assertEquals("1969-12-31 23:59:59.999999940", + scale7.getStringValue()); + TimeStampNsLiteral scale8 = new TimeStampNsLiteral("1969-12-31 23:59:59.999999995"); + Assertions.assertEquals("1969-12-31 23:59:59.999999995", + scale8.getStringValue()); + for (String value : new String[] { + "2024-02-29 12:34:56.1234567", + "2024-02-29 12:34:56.12345678", + "2024-02-29 12:34:56.123456789"}) { + DateTimeV2Type inferredType = DateTimeV2Type.forTypeFromString(value); + Assertions.assertEquals(DateTimeV2Type.MAX_SCALE, inferredType.getScale()); + Assertions.assertFalse(inferredType.isTimeStampNsType()); + } + + Assertions.assertDoesNotThrow(() -> + new TimeStampNsLiteral("1677-09-21 00:12:43.145224192")); + Assertions.assertDoesNotThrow(() -> + new TimeStampNsLiteral("2262-04-11 23:47:16.854775807")); + Assertions.assertEquals(Long.MIN_VALUE, + new TimeStampNsLiteral("1677-09-21 00:12:43.145224192") + .toLegacyLiteral().getRealValue()); + Assertions.assertEquals(Long.MAX_VALUE, + new TimeStampNsLiteral("2262-04-11 23:47:16.854775807") + .toLegacyLiteral().getRealValue()); + Assertions.assertThrows(AnalysisException.class, () -> + new TimeStampNsLiteral("1677-09-21 00:12:43.145224191")); + Assertions.assertThrows(AnalysisException.class, () -> + new TimeStampNsLiteral("2262-04-11 23:47:16.854775808")); + } + @Test void testSuffixSpace() { new DateLiteral("2016-07-02 "); diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteralTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteralTest.java index c3556f1bef4bcb..d626d43bfae85d 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteralTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteralTest.java @@ -17,6 +17,8 @@ package org.apache.doris.nereids.trees.expressions.literal; +import org.apache.doris.catalog.MysqlColType; +import org.apache.doris.common.Config; import org.apache.doris.nereids.exceptions.AnalysisException; import org.apache.doris.nereids.exceptions.CastException; import org.apache.doris.nereids.trees.expressions.Expression; @@ -36,10 +38,39 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.util.function.Consumer; import java.util.function.Function; class DateTimeLiteralTest { + @Test + void testMysqlTimestampKeepsMicrosecondRange() { + boolean previousEnableDateConversion = Config.enable_date_conversion; + try { + Config.enable_date_conversion = true; + ByteBuffer data = ByteBuffer.allocate(12).order(ByteOrder.LITTLE_ENDIAN); + data.put((byte) 11) + .putChar((char) 3022) + .put((byte) 1) + .put((byte) 2) + .put((byte) 3) + .put((byte) 4) + .put((byte) 5) + .putInt(123456) + .flip(); + + Literal literal = Literal.getLiteralByMysqlType( + MysqlColType.MYSQL_TYPE_DATETIME, false, data); + + DateTimeV2Literal dateTime = Assertions.assertInstanceOf(DateTimeV2Literal.class, literal); + Assertions.assertEquals(DateTimeV2Type.MAX, dateTime.getDataType()); + Assertions.assertEquals("3022-01-02 03:04:05.123456", dateTime.getStringValue()); + } finally { + Config.enable_date_conversion = previousEnableDateConversion; + } + } + @Test void reject() { // Assertions.assertThrows(IllegalArgumentException.class, () -> { @@ -402,28 +433,52 @@ void testIrregularDateTimeHourMinuteSecondMicrosecond() { check("2016-07-02 01:01:01.123456", DateTimeV2Literal::new); check("2016-7-02 01:01:01.123456", DateTimeV2Literal::new); - // Testing with microsecond of length 7 - DateTimeV2Literal literal = check("2016-07-02 01:01:01.12345678", DateTimeV2Literal::new); - Assertions.assertEquals(123457, literal.microSecond); - - literal = check("2016-07-02 01:01:01.44444444", DateTimeV2Literal::new); - Assertions.assertEquals(444444, literal.microSecond); - - literal = check("2016-07-02 01:01:01.44444445", DateTimeV2Literal::new); - Assertions.assertEquals(444444, literal.microSecond); - - literal = check("2016-07-02 01:01:01.4444445", DateTimeV2Literal::new); - Assertions.assertEquals(444445, literal.microSecond); - - literal = check("2016-07-02 01:01:01.9999995", DateTimeV2Literal::new); - Assertions.assertEquals(0, literal.microSecond); - Assertions.assertEquals(2, literal.second); - - literal = check("2021-01-01 23:59:59.9999995", DateTimeV2Literal::new); - Assertions.assertEquals(0, literal.microSecond); - Assertions.assertEquals(0, literal.second); - Assertions.assertEquals(0, literal.minute); - Assertions.assertEquals(0, literal.hour); + DateTimeV2Literal dateTimeV2 = check( + "2016-07-02 01:01:01.12345678", DateTimeV2Literal::new); + Assertions.assertEquals(123457, dateTimeV2.microSecond); + dateTimeV2 = check("2016-07-02 01:01:01.44444444", DateTimeV2Literal::new); + Assertions.assertEquals(444444, dateTimeV2.microSecond); + dateTimeV2 = check("2016-07-02 01:01:01.44444445", DateTimeV2Literal::new); + Assertions.assertEquals(444444, dateTimeV2.microSecond); + dateTimeV2 = check("2016-07-02 01:01:01.4444445", DateTimeV2Literal::new); + Assertions.assertEquals(444445, dateTimeV2.microSecond); + dateTimeV2 = check("2016-07-02 01:01:01.9999995", DateTimeV2Literal::new); + Assertions.assertEquals(0, dateTimeV2.microSecond); + Assertions.assertEquals(2, dateTimeV2.second); + dateTimeV2 = check("2021-01-01 23:59:59.9999995", DateTimeV2Literal::new); + Assertions.assertEquals(0, dateTimeV2.microSecond); + Assertions.assertEquals(0, dateTimeV2.second); + Assertions.assertEquals(0, dateTimeV2.minute); + Assertions.assertEquals(0, dateTimeV2.hour); + + // Fractional digits above microsecond precision are preserved by TIMESTAMP_NS literals. + TimeStampNsLiteral literal = check("2016-07-02 01:01:01.12345678", TimeStampNsLiteral::new); + Assertions.assertEquals(123456, literal.getMicroSecond()); + Assertions.assertEquals(123456780, literal.getNanoSecond()); + + literal = check("2016-07-02 01:01:01.44444444", TimeStampNsLiteral::new); + Assertions.assertEquals(444444, literal.getMicroSecond()); + Assertions.assertEquals(444444440, literal.getNanoSecond()); + + literal = check("2016-07-02 01:01:01.44444445", TimeStampNsLiteral::new); + Assertions.assertEquals(444444, literal.getMicroSecond()); + Assertions.assertEquals(444444450, literal.getNanoSecond()); + + literal = check("2016-07-02 01:01:01.4444445", TimeStampNsLiteral::new); + Assertions.assertEquals(444444, literal.getMicroSecond()); + Assertions.assertEquals(444444500, literal.getNanoSecond()); + + literal = check("2016-07-02 01:01:01.9999995", TimeStampNsLiteral::new); + Assertions.assertEquals(999999, literal.getMicroSecond()); + Assertions.assertEquals(999999500, literal.getNanoSecond()); + Assertions.assertEquals(1, literal.getSecond()); + + literal = check("2021-01-01 23:59:59.9999995", TimeStampNsLiteral::new); + Assertions.assertEquals(999999, literal.getMicroSecond()); + Assertions.assertEquals(999999500, literal.getNanoSecond()); + Assertions.assertEquals(59, literal.getSecond()); + Assertions.assertEquals(59, literal.getMinute()); + Assertions.assertEquals(23, literal.getHour()); } @Test @@ -458,6 +513,25 @@ void testDateTimeV2Scale() { check("2017-01-01 00:00:00.00000", s -> new DateTimeV2Literal(DateTimeV2Type.of(5), s))); } + @Test + void testTimeStampNsGuardDigitRounding() { + TimeStampNsLiteral literal = new TimeStampNsLiteral("1970-01-01 00:00:00.1234567894"); + Assertions.assertEquals("1970-01-01 00:00:00.123456789", literal.getStringValue()); + + literal = new TimeStampNsLiteral("1970-01-01 00:00:00.1234567895"); + Assertions.assertEquals("1970-01-01 00:00:00.123456790", literal.getStringValue()); + + literal = new TimeStampNsLiteral("1970-01-01 00:00:00.9999999995"); + Assertions.assertEquals("1970-01-01 00:00:01.000000000", literal.getStringValue()); + + literal = new TimeStampNsLiteral("1970-01-01 00:00:00.1234567845"); + Assertions.assertEquals("1970-01-01 00:00:00.123456785", literal.getStringValue()); + + DateTimeLiteral parsed = DateTimeLiteral.parseDateTimeLiteral( + "1970-01-01 00:00:00.9999999995", true).get(); + Assertions.assertEquals("1970-01-01 00:00:01.000000", parsed.getStringValue()); + } + @Test void testRoundFloor() { DateTimeV2Literal literal; @@ -625,7 +699,8 @@ void testDateTimeV1UncheckedCastTo() { @Test void testDateTimeV2UncheckedCastTo() { - DateTimeV2Literal v2 = new DateTimeV2Literal(DateTimeV2Type.MAX, 2025, 7, 23, 13, 25, 59, 999999); + DateTimeV2Literal v2 = new DateTimeV2Literal( + DateTimeV2Type.of(6), 2025, 7, 23, 13, 25, 59, 999999); Expression expression = v2.uncheckedCastTo(BigIntType.INSTANCE); Assertions.assertInstanceOf(BigIntLiteral.class, expression); @@ -689,9 +764,17 @@ void testDateTimeV2UncheckedCastTo() { Assertions.assertInstanceOf(StringLiteral.class, expression); Assertions.assertEquals("2025-07-23 13:25:59", ((StringLiteral) expression).value); - v2 = new DateTimeV2Literal(DateTimeV2Type.MAX, 2025, 7, 23, 13, 25, 59, 0); + v2 = new DateTimeV2Literal(DateTimeV2Type.of(6), 2025, 7, 23, 13, 25, 59, 0); expression = v2.uncheckedCastTo(StringType.INSTANCE); Assertions.assertInstanceOf(StringLiteral.class, expression); Assertions.assertEquals("2025-07-23 13:25:59.000000", ((StringLiteral) expression).value); } + + @Test + void testTimestampNsEpochNanoBoundaries() { + Assertions.assertEquals("1677-09-21 00:12:43.145224192", + TimeStampNsLiteral.getMinValue().getStringValue()); + Assertions.assertEquals("2262-04-11 23:47:16.854775807", + TimeStampNsLiteral.getMaxValue().getStringValue()); + } } diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/IntegerLiteralTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/IntegerLiteralTest.java index 0a9a34f669418b..a1af7a9647b9bc 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/IntegerLiteralTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/IntegerLiteralTest.java @@ -187,6 +187,10 @@ void testUncheckedCastTo() { Assertions.assertEquals(0, ((DateTimeV2Literal) expression).second); Assertions.assertEquals(0, ((DateTimeV2Literal) expression).microSecond); + IntegerLiteral invalidDate = new IntegerLiteral(1000); + Assertions.assertThrows(CastException.class, + () -> invalidDate.uncheckedCastTo(DateTimeV2Type.SYSTEM_DEFAULT)); + // to string d1 = new IntegerLiteral(701231); expression = d1.uncheckedCastTo(StringType.INSTANCE); diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/TimeStampNsLiteralTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/TimeStampNsLiteralTest.java new file mode 100644 index 00000000000000..9e037461c0dd6b --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/TimeStampNsLiteralTest.java @@ -0,0 +1,199 @@ +// 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. + +package org.apache.doris.nereids.trees.expressions.literal; + +import org.apache.doris.catalog.Type; +import org.apache.doris.nereids.exceptions.AnalysisException; +import org.apache.doris.nereids.exceptions.CastException; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.types.BigIntType; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.LargeIntType; +import org.apache.doris.nereids.types.TimeStampNsType; +import org.apache.doris.nereids.types.TimeV2Type; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.time.LocalDateTime; + +class TimeStampNsLiteralTest { + + @Test + void testFactoriesAndAccessors() { + TimeStampNsLiteral min = TimeStampNsLiteral.getMinValue(); + TimeStampNsLiteral max = TimeStampNsLiteral.getMaxValue(); + Assertions.assertEquals("1677-09-21 00:12:43.145224192", min.getStringValue()); + Assertions.assertEquals("2262-04-11 23:47:16.854775807", max.getStringValue()); + + TimeStampNsLiteral endOfDay = TimeStampNsLiteral.createEndOfDay(2024, 1, 2); + Assertions.assertEquals("2024-01-02 23:59:59.999999999", endOfDay.getStringValue()); + Assertions.assertFalse(endOfDay.isMidnight()); + + LocalDateTime dateTime = LocalDateTime.of(2024, 1, 2, 3, 4, 5, 123456789); + TimeStampNsLiteral literal = TimeStampNsLiteral.fromJavaDateType(dateTime); + Assertions.assertEquals(dateTime, literal.toJavaDateType()); + Assertions.assertSame(TimeStampNsType.INSTANCE, literal.getDataType()); + Assertions.assertEquals(20240102030405L, literal.getValue()); + Assertions.assertEquals(3, literal.getHour()); + Assertions.assertEquals(4, literal.getMinute()); + Assertions.assertEquals(5, literal.getSecond()); + Assertions.assertEquals(123456, literal.getMicroSecond()); + Assertions.assertEquals(123456789, literal.getNanoSecond()); + Assertions.assertEquals(TimeStampNsType.SCALE, literal.getScale()); + Assertions.assertEquals(11045123456789L, literal.getTimePartInNanoseconds()); + Assertions.assertEquals(123456789, literal.getFractionalSecondInNanoseconds()); + Assertions.assertEquals(20240102030405.123456789, literal.getDouble(), 0.001); + Assertions.assertEquals(literal.getStringValue(), literal.toLegacyLiteral().getStringValue()); + + TimeStampNsLiteral midnight = new TimeStampNsLiteral("2024-01-02 00:00:00.000000000"); + Assertions.assertTrue(midnight.isMidnight()); + Assertions.assertNotEquals(literal, literal.getStringValue()); + } + + @Test + void testTimeZoneAndGuardDigitParsing() { + TimeStampNsLiteral withTimeZone = new TimeStampNsLiteral( + "2024-01-02 03:04:05.123456789+00:00"); + Assertions.assertEquals(123456789, withTimeZone.getNanoSecond()); + + TimeStampNsLiteral rounded = new TimeStampNsLiteral( + "2024-01-02 03:04:05.9999999995"); + Assertions.assertEquals(0, rounded.getNanoSecond()); + Assertions.assertEquals(6, rounded.getSecond()); + } + + @Test + void testRoundToDateTimeV2() { + TimeStampNsLiteral literal = new TimeStampNsLiteral("2024-01-02 03:04:05.123456789"); + Assertions.assertEquals("2024-01-02 03:04:05.123456", + literal.roundFloorToDateTimeV2(6).getStringValue()); + Assertions.assertEquals("2024-01-02 03:04:05.123457", + literal.roundCeilingToDateTimeV2(6).getStringValue()); + + TimeStampNsLiteral exact = new TimeStampNsLiteral("2024-01-02 03:04:05.123456000"); + Assertions.assertEquals("2024-01-02 03:04:05.123456", + exact.roundCeilingToDateTimeV2(6).getStringValue()); + } + + @Test + void testInvalidCivilFieldsAndEpochBounds() { + Assertions.assertThrows(AnalysisException.class, + () -> new TimeStampNsLiteral(2024, 13, 1, 0, 0, 0, 0)); + Assertions.assertThrows(AnalysisException.class, + () -> new TimeStampNsLiteral(2024, 1, 1, 24, 0, 0, 0)); + Assertions.assertThrows(AnalysisException.class, + () -> new TimeStampNsLiteral(2024, 1, 1, 0, 60, 0, 0)); + Assertions.assertThrows(AnalysisException.class, + () -> new TimeStampNsLiteral(2024, 1, 1, 0, 0, 60, 0)); + Assertions.assertThrows(AnalysisException.class, + () -> new TimeStampNsLiteral(2024, 1, 1, 0, 0, 0, 1_000_000_000)); + Assertions.assertThrows(AnalysisException.class, + () -> new TimeStampNsLiteral("1677-09-21 00:12:43.145224191")); + Assertions.assertThrows(AnalysisException.class, + () -> new TimeStampNsLiteral("2262-04-11 23:47:16.854775808")); + } + + @Test + void testTimestampNsTypeContract() { + Assertions.assertEquals("timestamp_ns", TimeStampNsType.INSTANCE.toSql()); + Assertions.assertTrue(TimeStampNsType.INSTANCE.toCatalogDataType().isTimeStampNs()); + Assertions.assertSame(TimeStampNsType.INSTANCE, + TimeStampNsType.INSTANCE.scaleTypeForType(IntegerType.INSTANCE)); + Assertions.assertSame(TimeStampNsType.INSTANCE, + TimeStampNsType.INSTANCE.forTypeFromString(new StringLiteral("2024-01-02"))); + } + + @Test + void testLegacyConversionAndLiteralCasts() { + org.apache.doris.analysis.TimeStampNsLiteral legacy = + new org.apache.doris.analysis.TimeStampNsLiteral( + 2024, 1, 2, 3, 4, 5, 123456789); + TimeStampNsLiteral converted = (TimeStampNsLiteral) Literal.fromLegacyLiteral( + legacy, Type.TIMESTAMP_NS); + Assertions.assertEquals("2024-01-02 03:04:05.123456789", converted.getStringValue()); + + Expression fromString = new StringLiteral("2024-01-02 03:04:05.123456789") + .checkedCastTo(TimeStampNsType.INSTANCE); + Assertions.assertInstanceOf(TimeStampNsLiteral.class, fromString); + Assertions.assertThrows(CastException.class, + () -> new StringLiteral("2024-02-30 03:04:05.123456789") + .checkedCastTo(TimeStampNsType.INSTANCE)); + + Expression fromInteger = new BigIntLiteral(20240102030405L) + .checkedCastTo(TimeStampNsType.INSTANCE); + Assertions.assertEquals("2024-01-02 03:04:05.000000000", + ((TimeStampNsLiteral) fromInteger).getStringValue()); + } + + @Test + void testSupportedOutboundCastsAndRounding() { + TimeStampNsLiteral lower = TimeStampNsLiteral.getMinValue(); + TimeStampNsLiteral carry = new TimeStampNsLiteral("1969-12-31 23:59:59.999999999"); + TimeStampNsLiteral normal = new TimeStampNsLiteral("2024-02-29 12:34:56.123456789"); + TimeStampNsLiteral upper = TimeStampNsLiteral.getMaxValue(); + + Assertions.assertEquals("1677-09-21 00:12:43.145224", + ((Literal) lower.checkedCastTo(DateTimeV2Type.MAX)).getStringValue()); + Assertions.assertEquals("1970-01-01 00:00:00.000000", + ((Literal) carry.checkedCastTo(DateTimeV2Type.MAX)).getStringValue()); + Assertions.assertEquals("2024-02-29 12:34:56.123457", + ((Literal) normal.checkedCastTo(DateTimeV2Type.MAX)).getStringValue()); + Assertions.assertEquals("2262-04-11 23:47:16.854776", + ((Literal) upper.checkedCastTo(DateTimeV2Type.MAX)).getStringValue()); + + Assertions.assertEquals("2024-02-29", + ((Literal) normal.checkedCastTo(DateV2Type.INSTANCE)).getStringValue()); + Assertions.assertEquals("12:34:56.123457", + ((Literal) normal.checkedCastTo(TimeV2Type.MAX)).getStringValue()); + Assertions.assertEquals(20240229123456L, + ((BigIntLiteral) normal.checkedCastTo(BigIntType.INSTANCE)).getValue()); + Assertions.assertEquals("20240229123456", + ((LargeIntLiteral) normal.checkedCastTo(LargeIntType.INSTANCE)).getValue().toString()); + Assertions.assertThrows(AnalysisException.class, + () -> normal.checkedCastTo(IntegerType.INSTANCE)); + } + + @Test + void testSupportedInboundCastsCheckTimestampNsRange() { + Assertions.assertThrows(CastException.class, + () -> new DateV2Literal("1677-09-21").checkedCastTo(TimeStampNsType.INSTANCE)); + Assertions.assertEquals("1677-09-22 00:00:00.000000000", + ((Literal) new DateV2Literal("1677-09-22") + .checkedCastTo(TimeStampNsType.INSTANCE)).getStringValue()); + + Assertions.assertThrows(CastException.class, + () -> new DateTimeV2Literal(DateTimeV2Type.MAX, + "1677-09-21 00:12:43.145224") + .checkedCastTo(TimeStampNsType.INSTANCE)); + Assertions.assertEquals("1677-09-21 00:12:43.145225000", + ((Literal) new DateTimeV2Literal(DateTimeV2Type.MAX, + "1677-09-21 00:12:43.145225") + .checkedCastTo(TimeStampNsType.INSTANCE)).getStringValue()); + Assertions.assertEquals("2262-04-11 23:47:16.854775000", + ((Literal) new DateTimeV2Literal(DateTimeV2Type.MAX, + "2262-04-11 23:47:16.854775") + .checkedCastTo(TimeStampNsType.INSTANCE)).getStringValue()); + Assertions.assertThrows(CastException.class, + () -> new DateTimeV2Literal(DateTimeV2Type.MAX, + "2262-04-11 23:47:16.854776") + .checkedCastTo(TimeStampNsType.INSTANCE)); + } +} diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/OutFileTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/OutFileTest.java index 0d1c80af22c565..3793ddeba8f1f2 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/OutFileTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/OutFileTest.java @@ -49,7 +49,8 @@ protected void runBeforeAll() throws Exception { createTables( "CREATE TABLE IF NOT EXISTS T1 (\n" + " id bigint,\n" - + " score bigint\n" + + " score bigint,\n" + + " ts timestamp_ns\n" + ")\n" + "DUPLICATE KEY(id)\n" + "DISTRIBUTED BY HASH(id) BUCKETS 1\n" @@ -97,6 +98,14 @@ public void testHdfsOutFileCarriesDefaultFs() throws Exception { Assertions.assertEquals("hdfs://127.0.0.1:8020", sinkOptions.getBrokerProperties().get("fs.defaultFS")); } + @Test + public void testTimestampNsOrcOutfile() throws Exception { + String sql = "select ts from T1 into outfile 'file://~/timestamp_ns.orc' format as orc " + + "properties ('broker.name' = 'my_broker')"; + Assertions.assertTrue(getOutputFragment(sql).getExplainString(TExplainLevel.BRIEF) + .contains("FILE SINK")); + } + private PlanFragment getOutputFragment(String sql) throws Exception { StatementScopeIdGenerator.clear(); StatementContext statementContext = MemoTestUtils.createStatementContext(connectContext, sql); diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertUtilsTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertUtilsTest.java index 03cf24aab476a8..1991d7242cebb3 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertUtilsTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertUtilsTest.java @@ -17,6 +17,8 @@ package org.apache.doris.nereids.trees.plans.commands.insert; +import org.apache.doris.analysis.ColumnDef; +import org.apache.doris.analysis.DefaultValueExprDef; import org.apache.doris.catalog.Column; import org.apache.doris.catalog.PrimitiveType; import org.apache.doris.catalog.TableIf; @@ -28,6 +30,7 @@ import org.apache.doris.nereids.exceptions.AnalysisException; import org.apache.doris.nereids.trees.expressions.NamedExpression; import org.apache.doris.nereids.trees.expressions.literal.NullLiteral; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.trees.plans.logical.UnboundLogicalSink; import com.google.common.collect.ImmutableList; @@ -312,6 +315,21 @@ public void nativeDefaultStillExpandsExplicitDefault() { Assertions.assertEquals("7", expression.child(0).toSql()); } + @Test + public void timestampNsCurrentTimestampNineDefaultExpandsToLiteral() { + Column column = new Column("ts", Type.TIMESTAMP_NS, false, null, true, + ColumnDef.DefaultValue.CURRENT_TIMESTAMP + "(9)", "", true, + new DefaultValueExprDef(ColumnDef.DefaultValue.NOW, 9L), + Column.COLUMN_UNIQUE_ID_INIT_VALUE, null); + + NamedExpression expression = InsertUtils.generateDefaultExpression(column); + + TimeStampNsLiteral literal = Assertions.assertInstanceOf( + TimeStampNsLiteral.class, expression.child(0)); + Assertions.assertEquals(9, literal.getScale()); + Assertions.assertTrue(literal.getStringValue().matches(".*\\.\\d{9}")); + } + @Test public void nullableColumnWithoutDefaultStillExpandsToNull() { Column column = new Column("v", PrimitiveType.INT, true); diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/types/DataTypeTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/types/DataTypeTest.java index dc623fe4c642b6..6c3ccf45fb4c32 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/types/DataTypeTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/types/DataTypeTest.java @@ -17,12 +17,17 @@ package org.apache.doris.nereids.types; +import org.apache.doris.catalog.ScalarType; import org.apache.doris.catalog.Type; import org.apache.doris.nereids.exceptions.AnalysisException; +import org.apache.doris.nereids.trees.expressions.literal.StringLiteral; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.types.coercion.AnyDataType; +import org.apache.doris.nereids.types.coercion.DateLikeType; import org.apache.doris.nereids.types.coercion.FractionalType; import org.apache.doris.nereids.types.coercion.IntegralType; import org.apache.doris.nereids.types.coercion.NumericType; +import org.apache.doris.nereids.types.coercion.ScaleTimeType; import com.google.common.collect.ImmutableList; import org.junit.jupiter.api.Assertions; @@ -72,6 +77,58 @@ public void testDataTypeEquals() { @Test void testFromPrimitiveType() { Assertions.assertEquals(DataType.fromCatalogType(Type.STRING), StringType.INSTANCE); + Assertions.assertSame(TimeStampNsType.INSTANCE, + DataType.fromCatalogType(Type.TIMESTAMP_NS)); + Assertions.assertSame(TimeStampNsType.INSTANCE, + DataType.legacyTypeToNereidsType().get(Type.TIMESTAMP_NS.getPrimitiveType())); + } + + @Test + void testTimeStampNsValidation() { + DataType timestampNs = TimeStampNsType.INSTANCE; + Assertions.assertDoesNotThrow(timestampNs::validateDataType); + Assertions.assertInstanceOf(DateLikeType.class, timestampNs); + Assertions.assertInstanceOf(ScaleTimeType.class, timestampNs); + Assertions.assertTrue(timestampNs.isDateLikeType()); + Assertions.assertTrue(timestampNs.isTimeStampNsType()); + Assertions.assertFalse(timestampNs.isDateTimeV2Type()); + Assertions.assertFalse(timestampNs.isTimeStampTzType()); + Assertions.assertEquals(ScalarType.TIMESTAMP_NS_SCALE, TimeStampNsType.INSTANCE.getScale()); + Assertions.assertEquals(8, timestampNs.width()); + Assertions.assertEquals("timestamp_ns", timestampNs.toSql()); + Assertions.assertSame(TimeStampNsType.INSTANCE, + TimeStampNsType.INSTANCE.scaleTypeForType(DateTimeV2Type.MAX)); + Assertions.assertSame(TimeStampNsType.INSTANCE, + TimeStampNsType.INSTANCE.forTypeFromString( + new StringLiteral("2024-01-02 03:04:05.123456789"))); + Assertions.assertInstanceOf(TimeStampNsLiteral.class, + ((DateLikeType) timestampNs).fromString("2024-01-02 03:04:05.123456789")); + Assertions.assertEquals(86400, timestampNs.rangeLength(20240102000000D, 20240101000000D)); + Assertions.assertEquals(DateTimeV2Type.of(4), DateTimeV2Type.forType( + DecimalV2Type.createDecimalV2Type(12, 4))); + Assertions.assertEquals(DateTimeV2Type.of(5), DateTimeV2Type.forType( + DecimalV3Type.createDecimalV3Type(12, 5))); + } + + @Test + void testTimeV2PromotionKeepsMicrosecondPrecision() { + Assertions.assertEquals( + ImmutableList.of(DateTimeV2Type.MAX, StringType.INSTANCE), + TimeV2Type.of(6).getAllPromotions()); + } + + @Test + void testImplicitDateTimeV2PrecisionKeepsMicrosecondCompatibility() { + Assertions.assertEquals(DateTimeV2Type.MAX, + DateTimeV2Type.forType(StringType.INSTANCE)); + Assertions.assertEquals(DateTimeV2Type.MAX, + DateTimeV2Type.forType(DecimalV3Type.createDecimalV3Type(18, 9))); + Assertions.assertEquals(DateTimeV2Type.MAX, + DateTimeV2Type.forTypeFromString("1st Jun 2007 09:45:30")); + Assertions.assertEquals(DateTimeV2Type.MAX, + DateTimeV2Type.forType(DateTimeV2Type.MAX)); + Assertions.assertEquals(DateTimeV2Type.MAX, + DateTimeV2Type.forTypeFromString("2024-01-01 00:00:00.123456789")); } @Test @@ -121,6 +178,19 @@ void testConvertFromString() { // datetimev2 Assertions.assertEquals(DateTimeV2Type.of(3), DataType.convertFromString("datetimev2(3)")); + Assertions.assertSame(TimeStampNsType.INSTANCE, DataType.convertFromString("timestamp_ns")); + for (String datetimeType : ImmutableList.of("datetime", "datetimev2")) { + for (int invalidScale = 7; invalidScale <= 9; invalidScale++) { + int scale = invalidScale; + Assertions.assertThrows(AnalysisException.class, + () -> DataType.convertFromString(datetimeType + "(" + scale + ")")); + } + } + for (int invalidScale : ImmutableList.of(0, 1, 6, 7, 8, 9)) { + int scale = invalidScale; + Assertions.assertThrows(AnalysisException.class, + () -> DataType.convertFromString("timestamp_ns(" + scale + ")")); + } // hll Assertions.assertEquals(HllType.INSTANCE, DataType.convertFromString("hll")); // bitmap @@ -131,10 +201,18 @@ void testConvertFromString() { Assertions.assertEquals(JsonType.INSTANCE, DataType.convertFromString("json")); // array Assertions.assertEquals(ArrayType.of(IntegerType.INSTANCE), DataType.convertFromString("array")); + Assertions.assertEquals(ArrayType.of(TimeStampNsType.INSTANCE), + DataType.convertFromString("array")); // map Assertions.assertEquals(MapType.of(IntegerType.INSTANCE, IntegerType.INSTANCE), DataType.convertFromString("map")); + Assertions.assertEquals(MapType.of(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE), + DataType.convertFromString("map")); // struct Assertions.assertEquals(new StructType(ImmutableList.of(new StructField("a", IntegerType.INSTANCE, true, ""))), DataType.convertFromString("struct")); + Assertions.assertEquals( + new StructType(ImmutableList.of( + new StructField("ts", TimeStampNsType.INSTANCE, true, ""))), + DataType.convertFromString("struct")); } @@ -159,6 +237,10 @@ public void testIsInjectiveCastToForPrimitiveTypes() { assertSafeCast(DateTimeV2Type.of(3), DateTimeV2Type.of(6)); assertUnsafeCast(DateTimeV2Type.of(3), DateTimeType.INSTANCE); assertUnsafeCast(DateTimeType.INSTANCE, DateType.INSTANCE); + assertSafeCast(TimeStampNsType.INSTANCE, TimeStampNsType.INSTANCE); + assertSafeCast(TimeStampNsType.INSTANCE, StringType.INSTANCE); + assertUnsafeCast(TimeStampNsType.INSTANCE, DateTimeV2Type.MAX); + assertUnsafeCast(DateTimeV2Type.MAX, TimeStampNsType.INSTANCE); assertSafeCast(VarcharType.createVarcharType(10), VarcharType.createVarcharType(20)); assertSafeCast(VarcharType.createVarcharType(10), StringType.INSTANCE); diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/TypeCoercionMatrixTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/util/TypeCoercionMatrixTest.java index e654a2794bd237..4f4734964b4951 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/TypeCoercionMatrixTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/util/TypeCoercionMatrixTest.java @@ -45,6 +45,8 @@ import org.apache.doris.nereids.types.StringType; import org.apache.doris.nereids.types.StructField; import org.apache.doris.nereids.types.StructType; +import org.apache.doris.nereids.types.TimeStampNsType; +import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.TimeV2Type; import org.apache.doris.nereids.types.TinyIntType; import org.apache.doris.nereids.types.VarcharType; @@ -695,6 +697,13 @@ public void testProcessComparisonPredicateForDateTimeV2Type() { testProcessComparisonPredicate(DateTimeV2Type.of(4), CharType.createCharType(5), DateTimeV2Type.of(6)); testProcessComparisonPredicate(DateTimeV2Type.of(4), VarcharType.createVarcharType(5), DateTimeV2Type.of(6)); testProcessComparisonPredicate(DateTimeV2Type.of(4), StringType.INSTANCE, DateTimeV2Type.of(6)); + testProcessComparisonPredicate(TimeStampNsType.INSTANCE, DecimalV2Type.SYSTEM_DEFAULT, + TimeStampNsType.INSTANCE); + testProcessComparisonPredicate(TimeStampNsType.INSTANCE, DateV2Type.INSTANCE, TimeStampNsType.INSTANCE); + testProcessComparisonPredicate(TimeStampNsType.INSTANCE, DateTimeV2Type.MAX, TimeStampNsType.INSTANCE); + testProcessComparisonPredicate(TimeStampNsType.INSTANCE, TimeStampTzType.MAX, TimeStampNsType.INSTANCE); + testProcessComparisonPredicate(TimeStampNsType.INSTANCE, TimeV2Type.MAX, TimeStampNsType.INSTANCE); + testProcessComparisonPredicate(TimeStampNsType.INSTANCE, StringType.INSTANCE, TimeStampNsType.INSTANCE); testProcessComparisonPredicate(DateTimeV2Type.of(4), ArrayType.of(StringType.INSTANCE), null); testProcessComparisonPredicate(DateTimeV2Type.of(4), MapType.of(StringType.INSTANCE, StringType.INSTANCE), null); testProcessComparisonPredicate(DateTimeV2Type.of(4), new StructType(ImmutableList.of(new StructField("c1", StringType.INSTANCE, true, ""))), null); diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/TypeCoercionUtilsTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/util/TypeCoercionUtilsTest.java index 45c9b75afabfc4..96955c72a907d2 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/TypeCoercionUtilsTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/util/TypeCoercionUtilsTest.java @@ -18,6 +18,7 @@ package org.apache.doris.nereids.util; import org.apache.doris.nereids.exceptions.AnalysisException; +import org.apache.doris.nereids.rules.analysis.ExpressionAnalyzer; import org.apache.doris.nereids.rules.expression.check.CheckCast; import org.apache.doris.nereids.trees.expressions.Add; import org.apache.doris.nereids.trees.expressions.Cast; @@ -27,6 +28,7 @@ import org.apache.doris.nereids.trees.expressions.GreaterThan; import org.apache.doris.nereids.trees.expressions.InPredicate; import org.apache.doris.nereids.trees.expressions.Multiply; +import org.apache.doris.nereids.trees.expressions.Not; import org.apache.doris.nereids.trees.expressions.NullSafeEqual; import org.apache.doris.nereids.trees.expressions.SlotReference; import org.apache.doris.nereids.trees.expressions.Subtract; @@ -36,6 +38,10 @@ import org.apache.doris.nereids.trees.expressions.functions.agg.Sum; import org.apache.doris.nereids.trees.expressions.functions.scalar.Coalesce; import org.apache.doris.nereids.trees.expressions.functions.scalar.ElementAt; +import org.apache.doris.nereids.trees.expressions.functions.scalar.If; +import org.apache.doris.nereids.trees.expressions.functions.scalar.NullIf; +import org.apache.doris.nereids.trees.expressions.functions.scalar.Nvl; +import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral; import org.apache.doris.nereids.trees.expressions.literal.CharLiteral; import org.apache.doris.nereids.trees.expressions.literal.DateLiteral; import org.apache.doris.nereids.trees.expressions.literal.DateTimeLiteral; @@ -48,12 +54,14 @@ import org.apache.doris.nereids.trees.expressions.literal.NullLiteral; import org.apache.doris.nereids.trees.expressions.literal.StringLiteral; import org.apache.doris.nereids.trees.expressions.literal.StructLiteral; +import org.apache.doris.nereids.trees.expressions.literal.TimeStampNsLiteral; import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral; import org.apache.doris.nereids.types.ArrayType; import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.BitmapType; import org.apache.doris.nereids.types.BooleanType; import org.apache.doris.nereids.types.CharType; +import org.apache.doris.nereids.types.DataType; import org.apache.doris.nereids.types.DateTimeType; import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateType; @@ -73,11 +81,13 @@ import org.apache.doris.nereids.types.StringType; import org.apache.doris.nereids.types.StructField; import org.apache.doris.nereids.types.StructType; +import org.apache.doris.nereids.types.TimeStampNsType; import org.apache.doris.nereids.types.TimeStampTzType; import org.apache.doris.nereids.types.TimeV2Type; import org.apache.doris.nereids.types.TinyIntType; import org.apache.doris.nereids.types.VarcharType; import org.apache.doris.nereids.types.VariantType; +import org.apache.doris.nereids.types.coercion.AnyDataType; import org.apache.doris.nereids.types.coercion.IntegralType; import org.apache.doris.qe.ConnectContext; import org.apache.doris.qe.GlobalVariable; @@ -87,8 +97,214 @@ import org.junit.jupiter.api.Test; import java.math.BigDecimal; +import java.util.Optional; public class TypeCoercionUtilsTest { + @Test + public void testReplaceDateTimeV2WithMaxKeepsTimestampNsIndependent() { + Assertions.assertEquals(DateTimeV2Type.MAX, + TypeCoercionUtils.replaceDateTimeV2WithMax(DateTimeV2Type.of(3))); + Assertions.assertSame(TimeStampNsType.INSTANCE, + TypeCoercionUtils.replaceDateTimeV2WithMax(TimeStampNsType.INSTANCE)); + Assertions.assertEquals(ArrayType.of(TimeStampNsType.INSTANCE), + TypeCoercionUtils.replaceDateTimeV2WithMax(ArrayType.of(TimeStampNsType.INSTANCE))); + } + + @Test + public void testVariantWiderTypeKeepsTimestampNsPrecision() { + Assertions.assertEquals(Optional.of(TimeStampNsType.INSTANCE), + TypeCoercionUtils.findWiderTypeForTwo( + VariantType.INSTANCE, TimeStampNsType.INSTANCE, false, false)); + Assertions.assertEquals(Optional.of(ArrayType.of(TimeStampNsType.INSTANCE)), + TypeCoercionUtils.findWiderTypeForTwo( + VariantType.INSTANCE, ArrayType.of(TimeStampNsType.INSTANCE), false, false)); + + StructType mixedDateLikeType = new StructType(ImmutableList.of( + new StructField("ts", TimeStampNsType.INSTANCE, false, ""), + new StructField("date", DateV2Type.INSTANCE, true, ""))); + StructType normalizedMixedDateLikeType = new StructType(ImmutableList.of( + new StructField("ts", TimeStampNsType.INSTANCE, false, ""), + new StructField("date", DateTimeV2Type.MAX, true, ""))); + Assertions.assertEquals(Optional.of(normalizedMixedDateLikeType), + TypeCoercionUtils.findWiderTypeForTwo( + VariantType.INSTANCE, mixedDateLikeType, false, false)); + } + + @Test + public void testTimestampNsIsNotInDateTimeV2PrecisionFamily() { + Assertions.assertFalse(TypeCoercionUtils.hasDateTimeV2Type(TimeStampNsType.INSTANCE)); + Assertions.assertFalse(TypeCoercionUtils.hasDateTimeV2Type( + ArrayType.of(TimeStampNsType.INSTANCE))); + Assertions.assertTrue(TypeCoercionUtils.hasDateTimeV2Type(DateTimeV2Type.MAX)); + } + + @Test + public void testTimestampNsUsesLosslessCommonType() { + Assertions.assertEquals(Optional.of(TimeStampNsType.INSTANCE), + TypeCoercionUtils.findWiderTypeForTwo( + TimeStampNsType.INSTANCE, StringType.INSTANCE, false, false)); + Assertions.assertEquals(Optional.of(StringType.INSTANCE), + TypeCoercionUtils.findWiderTypeForTwo( + TimeStampNsType.INSTANCE, StringType.INSTANCE, false, true)); + Assertions.assertEquals(Optional.of(TimeStampNsType.INSTANCE), TypeCoercionUtils.findWiderTypeForTwo( + TimeStampNsType.INSTANCE, DateTimeV2Type.MAX, false, false)); + Assertions.assertEquals(Optional.of(TimeStampNsType.INSTANCE), TypeCoercionUtils.findWiderTypeForTwo( + DateV2Type.INSTANCE, TimeStampNsType.INSTANCE, false, false)); + Assertions.assertEquals(Optional.of(TimeStampNsType.INSTANCE), TypeCoercionUtils.findWiderTypeForTwo( + TimeStampNsType.INSTANCE, DecimalV2Type.SYSTEM_DEFAULT, false, false)); + + Assertions.assertEquals(Optional.of(TimeStampNsType.INSTANCE), + TypeCoercionUtils.implicitCast(StringType.INSTANCE, TimeStampNsType.INSTANCE)); + Assertions.assertEquals(Optional.of(StringType.INSTANCE), + TypeCoercionUtils.implicitCast(TimeStampNsType.INSTANCE, StringType.INSTANCE)); + Assertions.assertEquals(Optional.of(TimeStampNsType.INSTANCE), + TypeCoercionUtils.implicitCast(NullType.INSTANCE, TimeStampNsType.INSTANCE)); + Assertions.assertEquals(Optional.of(TimeStampNsType.INSTANCE), + TypeCoercionUtils.implicitCast( + TimeStampNsType.INSTANCE, AnyDataType.INSTANCE_WITHOUT_INDEX)); + Assertions.assertEquals(Optional.empty(), + TypeCoercionUtils.implicitCast(TimeStampNsType.INSTANCE, DateTimeV2Type.MAX)); + Assertions.assertEquals(Optional.of(TimeStampNsType.INSTANCE), + TypeCoercionUtils.implicitCast(DateTimeV2Type.MAX, TimeStampNsType.INSTANCE)); + } + + @Test + public void testTemporalCommonTypePrecedenceWithoutTimestampNs() { + Assertions.assertEquals(Optional.of(DateTimeV2Type.MAX), TypeCoercionUtils.findWiderTypeForTwo( + DateTimeV2Type.of(3), TimeStampTzType.MAX, false, false)); + Assertions.assertEquals(Optional.of(DateTimeV2Type.MAX), TypeCoercionUtils.findWiderTypeForTwo( + DateTimeV2Type.of(3), TimeV2Type.MAX, false, false)); + Assertions.assertEquals(Optional.of(DateTimeV2Type.MAX), TypeCoercionUtils.findWiderTypeForTwo( + TimeStampTzType.of(3), TimeV2Type.MAX, false, false)); + Assertions.assertEquals(Optional.of(TimeStampTzType.MAX), TypeCoercionUtils.findWiderTypeForTwo( + TimeStampTzType.of(3), TimeStampTzType.MAX, false, false)); + Assertions.assertEquals(Optional.of(TimeV2Type.MAX), TypeCoercionUtils.findWiderTypeForTwo( + TimeV2Type.of(3), TimeV2Type.MAX, false, false)); + } + + @Test + public void testTimestampNsComparisonCoercionInBothModes() { + boolean oldBehavior = GlobalVariable.enableNewTypeCoercionBehavior; + try { + for (boolean newBehavior : ImmutableList.of(false, true)) { + GlobalVariable.enableNewTypeCoercionBehavior = newBehavior; + + EqualTo stringComparison = (EqualTo) TypeCoercionUtils.processComparisonPredicate( + new EqualTo(new SlotReference("ts", TimeStampNsType.INSTANCE), + new SlotReference("s", StringType.INSTANCE))); + Assertions.assertEquals(TimeStampNsType.INSTANCE, + stringComparison.left().getDataType()); + Assertions.assertEquals(TimeStampNsType.INSTANCE, + stringComparison.right().getDataType()); + + ImmutableList temporalTypes = ImmutableList.of( + DateTimeV2Type.MAX, TimeStampTzType.MAX, TimeV2Type.MAX); + for (DataType temporalType : temporalTypes) { + EqualTo timestampNsOnLeft = (EqualTo) TypeCoercionUtils.processComparisonPredicate( + new EqualTo(new SlotReference("ts", TimeStampNsType.INSTANCE), + new SlotReference("temporal", temporalType))); + Assertions.assertEquals(TimeStampNsType.INSTANCE, + timestampNsOnLeft.left().getDataType()); + Assertions.assertEquals(TimeStampNsType.INSTANCE, + timestampNsOnLeft.right().getDataType()); + + EqualTo timestampNsOnRight = (EqualTo) TypeCoercionUtils.processComparisonPredicate( + new EqualTo(new SlotReference("temporal", temporalType), + new SlotReference("ts", TimeStampNsType.INSTANCE))); + Assertions.assertEquals(TimeStampNsType.INSTANCE, + timestampNsOnRight.left().getDataType()); + Assertions.assertEquals(TimeStampNsType.INSTANCE, + timestampNsOnRight.right().getDataType()); + } + + Assertions.assertEquals(Optional.of(TimeStampNsType.INSTANCE), + TypeCoercionUtils.findWiderCommonTypeByVariable( + ImmutableList.of(DateTimeV2Type.MAX, TimeStampTzType.MAX, + TimeV2Type.MAX, TimeStampNsType.INSTANCE), false, false)); + + InPredicate mixedIn = (InPredicate) TypeCoercionUtils.processInPredicate(new InPredicate( + new SlotReference("ts", TimeStampNsType.INSTANCE), ImmutableList.of( + new SlotReference("dt", DateTimeV2Type.MAX), + new SlotReference("tz", TimeStampTzType.MAX), + new SlotReference("time", TimeV2Type.MAX)))); + for (Expression child : mixedIn.children()) { + Assertions.assertEquals(TimeStampNsType.INSTANCE, child.getDataType()); + } + InPredicate timestampNsLast = (InPredicate) TypeCoercionUtils.processInPredicate(new InPredicate( + new SlotReference("dt", DateTimeV2Type.MAX), ImmutableList.of( + new SlotReference("tz", TimeStampTzType.MAX), + new SlotReference("time", TimeV2Type.MAX), + new SlotReference("ts", TimeStampNsType.INSTANCE)))); + for (Expression child : timestampNsLast.children()) { + Assertions.assertEquals(TimeStampNsType.INSTANCE, child.getDataType()); + } + + SlotReference timestampNs = new SlotReference("ts", TimeStampNsType.INSTANCE); + SlotReference datetime = new SlotReference("dt", DateTimeV2Type.MAX); + SlotReference timestampTz = new SlotReference("tz", TimeStampTzType.MAX); + SlotReference time = new SlotReference("time", TimeV2Type.MAX); + Assertions.assertEquals(TimeStampNsType.INSTANCE, + new If(BooleanLiteral.TRUE, timestampNs, timestampTz).getSignature().returnType); + Assertions.assertEquals(TimeStampNsType.INSTANCE, + new Nvl(timestampNs, datetime).getSignature().returnType); + Assertions.assertEquals(TimeStampNsType.INSTANCE, + new NullIf(timestampNs, time).getSignature().returnType); + Assertions.assertEquals(TimeStampNsType.INSTANCE, + new Coalesce(timestampNs, datetime, timestampTz, time).getSignature().returnType); + } + } finally { + GlobalVariable.enableNewTypeCoercionBehavior = oldBehavior; + } + } + + @Test + public void testTimestampNsLiteralAndCommonTypeCoercion() { + String timestamp = "2024-01-02 03:04:05.123456789"; + Optional literal = TypeCoercionUtils.characterLiteralTypeCoercion( + timestamp, TimeStampNsType.INSTANCE); + Assertions.assertTrue(literal.isPresent()); + Assertions.assertInstanceOf(TimeStampNsLiteral.class, literal.get()); + Assertions.assertEquals(TimeStampNsType.INSTANCE, literal.get().getDataType()); + Assertions.assertTrue(TypeCoercionUtils.characterLiteralTypeCoercion( + "2024-02-30 03:04:05.123456789", TimeStampNsType.INSTANCE).isEmpty()); + + SlotReference timestampSlot = new SlotReference("ts", TimeStampNsType.INSTANCE); + EqualTo rightString = TypeCoercionUtils.processCharacterLiteralInBinaryOperator( + new EqualTo(timestampSlot, new StringLiteral(timestamp))); + Assertions.assertInstanceOf(TimeStampNsLiteral.class, rightString.right()); + EqualTo leftString = TypeCoercionUtils.processCharacterLiteralInBinaryOperator( + new EqualTo(new StringLiteral(timestamp), timestampSlot)); + Assertions.assertInstanceOf(TimeStampNsLiteral.class, leftString.left()); + + Assertions.assertEquals(Optional.of(TimeStampNsType.INSTANCE), + TypeCoercionUtils.findWiderCommonTypeForComparison( + ImmutableList.of(StringType.INSTANCE, TimeStampNsType.INSTANCE))); + Assertions.assertEquals(Optional.of(TimeStampNsType.INSTANCE), + TypeCoercionUtils.findWiderCommonTypeForComparison( + ImmutableList.of(TimeStampNsType.INSTANCE, StringType.INSTANCE))); + Assertions.assertEquals(Optional.of(TimeStampNsType.INSTANCE), + TypeCoercionUtils.findCommonPrimitiveTypeForCaseWhen( + TimeStampNsType.INSTANCE, IntegerType.INSTANCE)); + + Assertions.assertSame(TimeStampNsType.INSTANCE, + TypeCoercionUtils.replaceTimesWithTargetPrecision(TimeStampNsType.INSTANCE, 6)); + MapType nestedTimestamp = MapType.of(IntegerType.INSTANCE, + ArrayType.of(TimeStampNsType.INSTANCE)); + Assertions.assertFalse(TypeCoercionUtils.hasDateTimeV2Type(nestedTimestamp)); + Assertions.assertEquals(nestedTimestamp, + TypeCoercionUtils.replaceTimesWithTargetPrecision(nestedTimestamp, 3)); + + MapType normalizedNestedTimestamp = MapType.of(DecimalV3Type.SYSTEM_DEFAULT, + ArrayType.of(TimeStampNsType.INSTANCE)); + Assertions.assertEquals(Optional.of(normalizedNestedTimestamp), + TypeCoercionUtils.findWiderTypeForTwo( + nestedTimestamp, VariantType.INSTANCE, false, false)); + Optional dateTargetWithTime = TypeCoercionUtils.characterLiteralTypeCoercion( + "2024-01-02 03:04:05.123456", DateV2Type.INSTANCE); + Assertions.assertTrue(dateTargetWithTime.isPresent()); + Assertions.assertEquals(DateTimeV2Type.of(6), dateTargetWithTime.get().getDataType()); + } + @Test public void testImplicitCastAccept() { IntegerType integerType = IntegerType.INSTANCE; @@ -483,6 +699,43 @@ public void testProcessInStringCoercion() { Assertions.assertEquals(DecimalV3Type.createDecimalV3Type(23, 3), smallIntString.getOptions().get(0).getDataType()); } + @Test + public void testDateStringSubMicrosecondComparisonCoercion() { + Expression date = new SlotReference("date", DateV2Type.INSTANCE, true); + Expression nanoString = new StringLiteral("2024-01-01 00:00:00.000000001"); + + // Preserve the nanosecond literal and promote DATEV2 to TIMESTAMP_NS in either direction. + EqualTo rightNano = (EqualTo) TypeCoercionUtils.processComparisonPredicate( + new EqualTo(date, nanoString)); + Assertions.assertEquals(TimeStampNsType.INSTANCE, rightNano.left().getDataType()); + Assertions.assertEquals(TimeStampNsType.INSTANCE, rightNano.right().getDataType()); + EqualTo leftNano = (EqualTo) TypeCoercionUtils.processComparisonPredicate( + new EqualTo(nanoString, date)); + Assertions.assertEquals(TimeStampNsType.INSTANCE, leftNano.left().getDataType()); + Assertions.assertEquals(TimeStampNsType.INSTANCE, leftNano.right().getDataType()); + } + + @Test + public void testDateStringSubMicrosecondInCoercion() { + Expression date = new SlotReference("date", DateV2Type.INSTANCE, true); + Expression nanoString = new StringLiteral("2024-01-01 00:00:00.000000001"); + Expression dateString = new StringLiteral("2024-01-02"); + + InPredicate in = (InPredicate) TypeCoercionUtils.processInPredicate( + new InPredicate(date, ImmutableList.of(nanoString, dateString))); + Assertions.assertEquals(TimeStampNsType.INSTANCE, in.getCompareExpr().getDataType()); + in.getOptions().forEach(option -> Assertions.assertEquals( + TimeStampNsType.INSTANCE, option.getDataType())); + + Expression notIn = ExpressionAnalyzer.FUNCTION_ANALYZER_RULE.rewrite( + new Not(new InPredicate(date, ImmutableList.of(dateString, nanoString))), null); + InPredicate rewrittenIn = (InPredicate) ((Not) notIn).child(); + Assertions.assertEquals(TimeStampNsType.INSTANCE, + rewrittenIn.getCompareExpr().getDataType()); + rewrittenIn.getOptions().forEach(option -> Assertions.assertEquals( + TimeStampNsType.INSTANCE, option.getDataType())); + } + @Test public void testCharacterLiteralTypeCoercion() { // datev2 diff --git a/fe/fe-core/src/test/java/org/apache/doris/planner/ConstantExpressTest.java b/fe/fe-core/src/test/java/org/apache/doris/planner/ConstantExpressTest.java index 5f80f11ead01b7..679568398afa9f 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/planner/ConstantExpressTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/planner/ConstantExpressTest.java @@ -40,7 +40,7 @@ protected void runBeforeAll() throws Exception { private void testConstantExpressResult(String sql, String result) throws Exception { String explainString = getSQLPlanOrErrorMsg("explain " + sql); System.out.println(explainString); - Assertions.assertTrue(explainString.contains("constant exprs: \n " + result)); + Assertions.assertTrue(explainString.contains("constant exprs: \n " + result), explainString); } @Test @@ -73,6 +73,10 @@ public void testDate() throws Exception { "select datediff('2018-08-08','1970-01-01');", "17751"); + testConstantExpressResult( + "select hour_ceil('1970-01-01 01:00:10', 1, '1970-01-01 00:00:30');", + "'1970-01-01 01:00:30'"); + testConstantExpressResult( "select date_add('2018-08-08', 1);", "'2018-08-09'"); diff --git a/fe/fe-core/src/test/java/org/apache/doris/qe/StmtExecutorTest.java b/fe/fe-core/src/test/java/org/apache/doris/qe/StmtExecutorTest.java index eb70a206b3a6d4..1fb0077ab4afa5 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/qe/StmtExecutorTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/qe/StmtExecutorTest.java @@ -22,6 +22,7 @@ import org.apache.doris.catalog.InternalSchemaInitializer; import org.apache.doris.catalog.PrimitiveType; import org.apache.doris.catalog.ResourceMgr; +import org.apache.doris.catalog.ScalarType; import org.apache.doris.common.Config; import org.apache.doris.common.FeConstants; import org.apache.doris.mysql.MysqlChannel; @@ -48,6 +49,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; @@ -332,6 +334,37 @@ public Void answer(InvocationOnMock invocation) { executor.sendBinaryResultRow(resultSet); } + @Test + public void testSendBinaryTimestampNsResultRow() throws IOException { + ConnectContext mockCtx = Mockito.mock(ConnectContext.class); + MysqlChannel channel = Mockito.mock(MysqlChannel.class); + Mockito.when(mockCtx.getConnectType()).thenReturn(ConnectType.MYSQL); + Mockito.when(mockCtx.getMysqlChannel()).thenReturn(channel); + MysqlSerializer mysqlSerializer = MysqlSerializer.newInstance(); + Mockito.when(channel.getSerializer()).thenReturn(mysqlSerializer); + Mockito.when(mockCtx.getSessionVariable()).thenReturn(VariableMgr.newSessionVariable()); + + String value = "2025-01-01 01:02:03.123456789"; + List> rows = Lists.newArrayList(); + rows.add(Lists.newArrayList(value)); + ResultSet resultSet = new CommonResultSet( + new CommonResultSetMetaData(Lists.newArrayList( + new Column("timestamp_ns", ScalarType.createTimeStampNsType()))), + rows); + Mockito.doAnswer(invocation -> { + byte[] valueBytes = value.getBytes(StandardCharsets.UTF_8); + byte[] expected = new byte[valueBytes.length + 3]; + expected[2] = (byte) valueBytes.length; + System.arraycopy(valueBytes, 0, expected, 3, valueBytes.length); + ByteBuffer buffer = invocation.getArgument(0); + Assertions.assertArrayEquals(expected, buffer.array()); + return null; + }).when(channel).sendOnePacket(Mockito.any(ByteBuffer.class)); + + StmtExecutor executor = new StmtExecutor(mockCtx, new OriginStatement("", 1), false); + executor.sendBinaryResultRow(resultSet); + } + @Test public void testSendBinaryBooleanResultRow() throws IOException { ConnectContext mockCtx = Mockito.mock(ConnectContext.class); diff --git a/fe/fe-core/src/test/java/org/apache/doris/service/arrowflight/FlightSqlSchemaHelperArrowTypeTest.java b/fe/fe-core/src/test/java/org/apache/doris/service/arrowflight/FlightSqlSchemaHelperArrowTypeTest.java index 147a52aa55ed98..f5ee41ae4e8c15 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/service/arrowflight/FlightSqlSchemaHelperArrowTypeTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/service/arrowflight/FlightSqlSchemaHelperArrowTypeTest.java @@ -26,6 +26,7 @@ import org.apache.arrow.vector.ipc.ReadChannel; import org.apache.arrow.vector.ipc.message.MessageSerializer; import org.apache.arrow.vector.types.DateUnit; +import org.apache.arrow.vector.types.TimeUnit; import org.apache.arrow.vector.types.pojo.ArrowType; import org.apache.arrow.vector.types.pojo.Field; import org.apache.arrow.vector.types.pojo.Schema; @@ -89,6 +90,12 @@ public void dateV2IsDescribedAsDate32() { buildField(desc("d", TPrimitiveType.DATEV2)).getType()); } + @Test + public void timestampNsIsDescribedAsNanosecondTimestamp() { + Assertions.assertEquals(new ArrowType.Timestamp(TimeUnit.NANOSECOND, "UTC"), + buildField(desc("ts", TPrimitiveType.TIMESTAMP_NS)).getType()); + } + /** * An Arrow list carries its element type in its child and nowhere else, so the placeholder child this * replaced ({@code ZeroVector}'s Null type) described every array in the catalog as an array OF diff --git a/fe/fe-grpc/pom.xml b/fe/fe-grpc/pom.xml index ef5c8b66847f91..c87c7a12188788 100644 --- a/fe/fe-grpc/pom.xml +++ b/fe/fe-grpc/pom.xml @@ -39,7 +39,7 @@ under the License. protoc_command - ${doris.thirdparty}/installed/bin/protoc + ${basedir}/../../thirdparty/installed/bin/protoc diff --git a/fe/fe-sql-parser/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4 b/fe/fe-sql-parser/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4 index 446685892295e4..d2ba7a1203b786 100644 --- a/fe/fe-sql-parser/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4 +++ b/fe/fe-sql-parser/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4 @@ -573,6 +573,7 @@ THEN: 'THEN'; TIME: 'TIME'; TIMESTAMP: 'TIMESTAMP'; TIMESTAMPTZ: 'TIMESTAMPTZ'; +TIMESTAMP_NS: 'TIMESTAMP_NS'; TINYINT: 'TINYINT'; TO: 'TO'; TOKENIZER: 'TOKENIZER'; diff --git a/fe/fe-sql-parser/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 b/fe/fe-sql-parser/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 index 4e149e29e0a311..76cc4d346465e7 100644 --- a/fe/fe-sql-parser/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 +++ b/fe/fe-sql-parser/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 @@ -1901,6 +1901,7 @@ primitiveColType | type=DATEV1 | type=DATETIMEV1 | type=TIMESTAMPTZ + | type=TIMESTAMP_NS | type=BITMAP | type=QUANTILE_STATE | type=HLL @@ -2365,6 +2366,7 @@ nonReserved | TIME | TIMESTAMP | TIMESTAMPTZ + | TIMESTAMP_NS | TRANSACTION | TREE | TRIGGERS diff --git a/fe/fe-type/src/main/java/org/apache/doris/catalog/PrimitiveType.java b/fe/fe-type/src/main/java/org/apache/doris/catalog/PrimitiveType.java index 216db92e21698a..36b640831772f1 100644 --- a/fe/fe-type/src/main/java/org/apache/doris/catalog/PrimitiveType.java +++ b/fe/fe-type/src/main/java/org/apache/doris/catalog/PrimitiveType.java @@ -66,6 +66,7 @@ public enum PrimitiveType { AGG_STATE("AGG_STATE", 16, TPrimitiveType.AGG_STATE, true), DATEV2("DATEV2", 4, TPrimitiveType.DATEV2, true), DATETIMEV2("DATETIMEV2", 8, TPrimitiveType.DATETIMEV2, true), + TIMESTAMP_NS("TIMESTAMP_NS", 8, TPrimitiveType.TIMESTAMP_NS, true), TIMEV2("TIMEV2", 8, TPrimitiveType.TIMEV2, false), TIMESTAMPTZ("TIMESTAMPTZ", 8, TPrimitiveType.TIMESTAMPTZ, false), LAMBDA_FUNCTION("LAMBDA_FUNCTION", 16, TPrimitiveType.LAMBDA_FUNCTION, false), @@ -135,6 +136,7 @@ public enum PrimitiveType { supportedTypes.add(DATETIME); supportedTypes.add(DATEV2); supportedTypes.add(DATETIMEV2); + supportedTypes.add(TIMESTAMP_NS); supportedTypes.add(TIMEV2); supportedTypes.add(TIMESTAMPTZ); supportedTypes.add(IPV4); @@ -213,6 +215,8 @@ public static PrimitiveType fromThrift(TPrimitiveType tPrimitiveType) { return DATEV2; case DATETIMEV2: return DATETIMEV2; + case TIMESTAMP_NS: + return TIMESTAMP_NS; case IPV4: return IPV4; case IPV6: @@ -328,11 +332,12 @@ public boolean isNull() { } public boolean isDateLikeType() { - return (this == DATE || this == DATETIME || this == DATEV2 || this == DATETIMEV2 || this == TIMESTAMPTZ); + return this == DATE || this == DATETIME || this == DATEV2 || this == DATETIMEV2 + || this == TIMESTAMP_NS || this == TIMESTAMPTZ; } public boolean isDateV2LikeType() { - return (this == DATEV2 || this == DATETIMEV2 || this == TIMESTAMPTZ); + return this == DATEV2 || this == DATETIMEV2 || this == TIMESTAMP_NS || this == TIMESTAMPTZ; } public boolean isTimeStampTzType() { @@ -428,6 +433,7 @@ public MysqlColType toMysqlType() { case DATEV2: return MysqlColType.MYSQL_TYPE_DATE; case TIMESTAMPTZ: + case TIMESTAMP_NS: return MysqlColType.MYSQL_TYPE_STRING; case DATETIME: case DATETIMEV2: { @@ -463,6 +469,7 @@ public int getOlapColumnIndexSize() { return DATEV2_INDEX_LEN; case DATETIME: case DATETIMEV2: + case TIMESTAMP_NS: case TIMESTAMPTZ: return DATETIME_INDEX_LEN; case VARCHAR: diff --git a/fe/fe-type/src/main/java/org/apache/doris/catalog/ScalarType.java b/fe/fe-type/src/main/java/org/apache/doris/catalog/ScalarType.java index 219a7c2384fc6c..b39bfbbd69f14c 100644 --- a/fe/fe-type/src/main/java/org/apache/doris/catalog/ScalarType.java +++ b/fe/fe-type/src/main/java/org/apache/doris/catalog/ScalarType.java @@ -81,6 +81,7 @@ public class ScalarType extends Type { public static final int MAX_DECIMAL256_PRECISION = 76; public static final int DEFAULT_MIN_AVG_DECIMAL128_SCALE = 4; public static final int MAX_DATETIMEV2_SCALE = 6; + public static final int TIMESTAMP_NS_SCALE = 9; public static final int MAX_PRECISION = MAX_DECIMAL256_PRECISION; private long byteSize = -1; @@ -146,6 +147,8 @@ public static ScalarType createType(PrimitiveType type, int len, int precision, return createDecimalType(precision, scale); case DATETIMEV2: return createDatetimeV2Type(scale); + case TIMESTAMP_NS: + return createTimeStampNsType(); case TIMEV2: return createTimeV2Type(scale); case TIMESTAMPTZ: @@ -205,6 +208,8 @@ public static ScalarType createType(PrimitiveType type) { return DATEV2; case DATETIMEV2: return DEFAULT_DATETIMEV2; + case TIMESTAMP_NS: + return Type.TIMESTAMP_NS; case TIMEV2: return TIMEV2; case TIMESTAMPTZ: @@ -281,6 +286,8 @@ public static ScalarType createType(String type) { return DATEV2; case "DATETIMEV2": return DATETIMEV2; + case "TIMESTAMP_NS": + return TIMESTAMP_NS; case "TIME": case "TIMEV2": return TIMEV2; @@ -451,6 +458,11 @@ public static ScalarType createDatetimeV2Type(int scale) { return type; } + @SuppressWarnings("checkstyle:MissingJavadocMethod") + public static ScalarType createTimeStampNsType() { + return new ScalarType(PrimitiveType.TIMESTAMP_NS); + } + @SuppressWarnings("checkstyle:MissingJavadocMethod") public static ScalarType createTimeV2Type(int scale) { ScalarType type = new ScalarType(PrimitiveType.TIMEV2); @@ -605,13 +617,15 @@ public String toString() { return "decimal(*,*)"; } return "decimal(" + precision + "," + scale + ")"; - } else if (type.isDecimalV3Type()) { + } else if (type.isDecimalV3Type()) { if (isWildcardDecimal()) { return "decimalv3(*,*)"; } return "decimalv3(" + precision + "," + scale + ")"; - } else if (type == PrimitiveType.DATETIMEV2) { + } else if (type == PrimitiveType.DATETIMEV2) { return "datetimev2(" + scale + ")"; + } else if (type == PrimitiveType.TIMESTAMP_NS) { + return "timestamp_ns"; } else if (type == PrimitiveType.TIMEV2) { return "timev2(" + scale + ")"; } else if (type == PrimitiveType.TIMESTAMPTZ) { @@ -680,6 +694,9 @@ public String toSql(int depth) { case DATETIMEV2: stringBuilder.append("datetimev2").append("(").append(scale).append(")"); break; + case TIMESTAMP_NS: + stringBuilder.append("timestamp_ns"); + break; case TIMEV2: stringBuilder.append("time").append("(").append(scale).append(")"); break; diff --git a/fe/fe-type/src/main/java/org/apache/doris/catalog/Type.java b/fe/fe-type/src/main/java/org/apache/doris/catalog/Type.java index 38dcd8f359c180..063cc55bf33d47 100644 --- a/fe/fe-type/src/main/java/org/apache/doris/catalog/Type.java +++ b/fe/fe-type/src/main/java/org/apache/doris/catalog/Type.java @@ -71,6 +71,7 @@ public abstract class Type { public static final ScalarType DATEV2 = new ScalarType(PrimitiveType.DATEV2); public static final ScalarType TIMEV2 = new ScalarType(PrimitiveType.TIMEV2); public static final ScalarType TIMESTAMPTZ = new ScalarType(PrimitiveType.TIMESTAMPTZ); + public static final ScalarType TIMESTAMP_NS = ScalarType.createTimeStampNsType(); public static final ScalarType STRING = ScalarType.createStringType(); public static final ScalarType VARBINARY = ScalarType.createVarbinaryType(-1); public static final ScalarType DEFAULT_DECIMALV2 = ScalarType.createDecimalType(PrimitiveType.DECIMALV2, @@ -97,7 +98,8 @@ public abstract class Type { public static final ScalarType DEFAULT_DECIMALV3 = DEFAULT_DECIMAL32; public static final ScalarType DEFAULT_DATETIMEV2 = ScalarType.createDatetimeV2Type(0); public static final ScalarType DATETIMEV2 = DEFAULT_DATETIMEV2; - public static final ScalarType DATETIMEV2_WITH_MAX_SCALAR = ScalarType.createDatetimeV2Type(6); + public static final ScalarType DATETIMEV2_WITH_MAX_SCALAR + = ScalarType.createDatetimeV2Type(ScalarType.MAX_DATETIMEV2_SCALE); public static final ScalarType DEFAULT_TIMESTAMP_TZ = ScalarType.createTimeStampTzType(0); public static final ScalarType TIMESTAMP_TZ = DEFAULT_TIMESTAMP_TZ; public static final ScalarType TIMESTAMP_TZ_WITH_MAX_SCALAR = ScalarType.createTimeStampTzType(6); @@ -165,6 +167,7 @@ public abstract class Type { numericDateTimeTypes.add(DATETIME); numericDateTimeTypes.add(DATEV2); numericDateTimeTypes.add(DATETIMEV2); + numericDateTimeTypes.add(TIMESTAMP_NS); numericDateTimeTypes.add(TIMEV2); numericDateTimeTypes.addAll(numericTypes); @@ -178,6 +181,7 @@ public abstract class Type { trivialTypes.add(DATETIME); trivialTypes.add(DATEV2); trivialTypes.add(DATETIMEV2); + trivialTypes.add(TIMESTAMP_NS); trivialTypes.add(IPV4); trivialTypes.add(IPV6); trivialTypes.add(TIMEV2); @@ -202,6 +206,7 @@ public abstract class Type { arraySubTypes.add(DATETIME); arraySubTypes.add(DATEV2); arraySubTypes.add(DATETIMEV2); + arraySubTypes.add(TIMESTAMP_NS); arraySubTypes.add(TIMESTAMP_TZ); arraySubTypes.add(IPV4); arraySubTypes.add(IPV6); @@ -232,6 +237,7 @@ public abstract class Type { mapSubTypes.add(DATETIME); mapSubTypes.add(DATEV2); mapSubTypes.add(DATETIMEV2); + mapSubTypes.add(TIMESTAMP_NS); mapSubTypes.add(TIMESTAMP_TZ); mapSubTypes.add(IPV4); mapSubTypes.add(IPV6); @@ -258,6 +264,7 @@ public abstract class Type { structSubTypes.add(DATETIME); structSubTypes.add(DATEV2); structSubTypes.add(DATETIMEV2); + structSubTypes.add(TIMESTAMP_NS); structSubTypes.add(TIMESTAMP_TZ); structSubTypes.add(IPV4); structSubTypes.add(IPV6); @@ -316,6 +323,7 @@ public abstract class Type { .put(PrimitiveType.DATEV2, DATE_SUPPORTED_JAVA_TYPE) .put(PrimitiveType.DATETIME, DATETIME_SUPPORTED_JAVA_TYPE) .put(PrimitiveType.DATETIMEV2, DATETIME_SUPPORTED_JAVA_TYPE) + .put(PrimitiveType.TIMESTAMP_NS, DATETIME_SUPPORTED_JAVA_TYPE) .put(PrimitiveType.LARGEINT, Sets.newHashSet(BigInteger.class)) .put(PrimitiveType.DECIMALV2, Sets.newHashSet(BigDecimal.class)) .put(PrimitiveType.DECIMAL32, Sets.newHashSet(BigDecimal.class)) @@ -490,6 +498,8 @@ public String hideVersionForVersionColumn( typeStr.append("(").append(((ScalarType) this).getScalarScale()).append(")"); } return typeStr.toString(); + } else if (isTimeStampNs()) { + return "timestamp_ns"; } else if (isTimeStampTz()) { StringBuilder typeStr = new StringBuilder("timestamptz"); if (((ScalarType) this).getScalarScale() > 0) { @@ -558,6 +568,10 @@ public boolean isDatetimeV2() { return isScalarType(PrimitiveType.DATETIMEV2); } + public boolean isTimeStampNs() { + return isScalarType(PrimitiveType.TIMESTAMP_NS); + } + public boolean isTimeV2() { return isScalarType(PrimitiveType.TIMEV2); } @@ -707,6 +721,7 @@ public boolean isNativeType() { public boolean isDateType() { return isScalarType(PrimitiveType.DATE) || isScalarType(PrimitiveType.DATETIME) || isScalarType(PrimitiveType.DATEV2) || isScalarType(PrimitiveType.DATETIMEV2) + || isScalarType(PrimitiveType.TIMESTAMP_NS) || isScalarType(PrimitiveType.TIMESTAMPTZ); } @@ -890,6 +905,8 @@ public static Type fromPrimitiveType(PrimitiveType type) { return Type.DATEV2; case DATETIMEV2: return Type.DATETIMEV2; + case TIMESTAMP_NS: + return Type.TIMESTAMP_NS; case TIMEV2: return Type.TIMEV2; case TIMESTAMPTZ: @@ -999,6 +1016,8 @@ protected static Pair fromThrift(TTypeDesc col, int nodeIdx) { Preconditions.checkState(scalarType.isSetPrecision() && scalarType.isSetScale()); type = ScalarType.createDatetimeV2Type(scalarType.getScale()); + } else if (scalarType.getType() == TPrimitiveType.TIMESTAMP_NS) { + type = ScalarType.createTimeStampNsType(); } else if (scalarType.getType() == TPrimitiveType.TIMEV2) { Preconditions.checkState(scalarType.isSetPrecision() && scalarType.isSetScale()); @@ -1140,6 +1159,8 @@ public Integer getPrecision() { case TIMESTAMPTZ: case TIMEV2: return t.decimalPrecision(); + case TIMESTAMP_NS: + return 29; default: return null; } @@ -1176,6 +1197,8 @@ public Integer getDecimalDigits() { case DECIMAL128: case DECIMAL256: return t.decimalScale(); + case TIMESTAMP_NS: + return 9; default: return null; } diff --git a/gensrc/proto/types.proto b/gensrc/proto/types.proto index 1cb49602e60a76..51acb7cb8ca324 100644 --- a/gensrc/proto/types.proto +++ b/gensrc/proto/types.proto @@ -122,6 +122,7 @@ message PGenericType { IPV6 = 40; VARBINARY = 41; TIMESTAMPTZ = 42; + TIMESTAMP_NS = 43; UNKNOWN = 999; } required TypeId id = 2; diff --git a/gensrc/thrift/Types.thrift b/gensrc/thrift/Types.thrift index f911d17346f1f9..daef6845d5c871 100644 --- a/gensrc/thrift/Types.thrift +++ b/gensrc/thrift/Types.thrift @@ -102,7 +102,8 @@ enum TPrimitiveType { UINT64 = 41, // only used in BE to represent offsets FIXED_LENGTH_OBJECT = 42 // only used in BE to represent fixed-length object VARBINARY = 43, // represent varbinary type - TIMESTAMPTZ = 44 // timestamp with time zone + TIMESTAMPTZ = 44, // timestamp with time zone + TIMESTAMP_NS = 45 // signed nanoseconds since the Unix epoch } enum TTypeNodeType { diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_agg_state.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_agg_state.out new file mode 100644 index 00000000000000..cb1c923d772458 --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_agg_state.out @@ -0,0 +1,3 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !aggregate_state -- +1 2262-04-11 23:47:16.854775807 diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_binary_output.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_binary_output.out new file mode 100644 index 00000000000000..fe08ef9c96096e --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_binary_output.out @@ -0,0 +1,16 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !text_protocol -- +1 1677-09-21 00:12:43.145224192 +2 1969-12-31 23:59:59.999999999 +3 1970-01-01 00:00:00.000000000 +4 1970-01-01 00:00:00.000000001 +5 2262-04-11 23:47:16.854775807 +6 \N + +-- !binary_protocol -- +1 1677-09-21 00:12:43.145224192 +2 1969-12-31 23:59:59.999999999 +3 1970-01-01 00:00:00.000000000 +4 1970-01-01 00:00:00.000000001 +5 2262-04-11 23:47:16.854775807 +6 \N diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_cast.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_cast.out new file mode 100644 index 00000000000000..9425ce117b932f --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_cast.out @@ -0,0 +1,76 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !string_to_timestamp_ns -- +1 \N +10 2024-02-29 12:34:56.123456789 +11 2024-02-29 12:34:56.123456789 +12 \N +13 \N +14 \N +2 1677-09-21 00:12:43.145224192 +3 1969-12-31 23:59:59.999999999 +4 1970-01-01 00:00:00.000000000 +5 2024-02-29 12:34:56.123456789 +6 2024-02-29 12:34:56.123456790 +7 2024-02-29 12:34:57.000000000 +8 2262-04-11 23:47:16.854775807 +9 \N + +-- !string_literal_fold -- +1677-09-21 00:12:43.145224192 1970-01-01 00:00:00.000000000 2024-02-29 12:34:57.000000000 2262-04-11 23:47:16.854775807 + +-- !string_literal_runtime -- +1677-09-21 00:12:43.145224192 1970-01-01 00:00:00.000000000 2024-02-29 12:34:57.000000000 2262-04-11 23:47:16.854775807 + +-- !numeric_to_timestamp_ns -- +2000-01-23 00:00:00.000000000 2000-12-31 00:00:00.000000000 2024-02-29 00:00:00.000000000 2024-02-29 12:34:56.000000000 2024-02-29 12:34:56.000000000 \N 2024-02-29 12:34:56.125000000 2024-02-29 12:34:56.123456790 2024-02-29 12:34:56.123456789 + +-- !datelike_to_timestamp_ns -- +1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 2024-02-29 12:34:56.000000000 2024-02-29 12:34:56.123456000 12:34:56.123456 2024-02-29 12:34:56.123456000 + +-- !all_supported_sources_fold -- +2000-01-23 00:00:00.000000000 2000-12-31 00:00:00.000000000 2024-02-29 00:00:00.000000000 2024-02-29 12:34:56.000000000 2024-02-29 12:34:56.000000000 2000-01-23 00:00:00.000000000 2024-02-29 12:34:56.125000000 2024-02-29 12:34:56.123456790 2024-02-29 12:34:56.123456789 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 2024-02-29 12:34:56.000000000 2024-02-29 12:34:56.123456000 12:34:56.123456 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456000 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 \N + +-- !all_supported_targets_fold -- +20240229123456 20240229123456 2024-02-29 2024-02-29 2024-02-29T12:34:56 2024-02-29T12:34:56.123457 12:34:56.123457 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123457+08:00 2.02402284E13 20240229123456 2024-02-29 12:34:56.123456789 + +-- !all_supported_sources_runtime -- +2000-01-23 00:00:00.000000000 2000-12-31 00:00:00.000000000 2024-02-29 00:00:00.000000000 2024-02-29 12:34:56.000000000 2024-02-29 12:34:56.000000000 2000-01-23 00:00:00.000000000 2024-02-29 12:34:56.125000000 2024-02-29 12:34:56.123456790 2024-02-29 12:34:56.123456789 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 2024-02-29 12:34:56.000000000 2024-02-29 12:34:56.123456000 12:34:56.123456 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456000 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 \N + +-- !all_supported_targets_runtime -- +20240229123456 20240229123456 2024-02-29 2024-02-29 2024-02-29T12:34:56 2024-02-29T12:34:56.123457 12:34:56.123457 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123457+08:00 2.02402284E13 20240229123456 2024-02-29 12:34:56.123456789 + +-- !typed_columns_to_timestamp_ns -- +1 2000-01-23 00:00:00.000000000 2000-12-31 00:00:00.000000000 2024-02-29 00:00:00.000000000 2024-02-29 12:34:56.000000000 2024-02-29 12:34:56.000000000 2000-01-23 00:00:00.000000000 2024-02-29 12:34:56.125000000 2024-02-29 12:34:56.123456790 2024-02-29 12:34:56.123456789 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 2024-02-29 12:34:56.000000000 2024-02-29 12:34:56.123456000 12:34:56.123456 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456000 2024-02-29 12:34:56.123456789 +2 \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N + +-- !timestamp_ns_to_supported_types -- +1 1677-09-21 1677-09-21 1677-09-21T00:12:43 1677-09-21T00:12:43 1677-09-21T00:12:43.145 1677-09-21T00:12:43.145224 00:12:43 00:12:43.145 00:12:43.145224 16770921001243 16770921001243 1677-09-21 00:12:43.145224192 1677-09-21 00:12:43.145224192 1677-09-21 00:12:43.145224192 1677-09-21 00:12:43.145224192 1677-09-21 00:12:43.145224192 1677-09-21 00:12:43.145224+08:00 1.67709214E13 16770921001243 +2 1969-12-31 1969-12-31 1970-01-01T00:00 1970-01-01T00:00 1970-01-01T00:00 1970-01-01T00:00 24:00:00 24:00:00.000 24:00:00.000000 19691231235959 19691231235959 1969-12-31 23:59:59.999999999 1969-12-31 23:59:59.999999999 1969-12-31 23:59:59.999999999 1969-12-31 23:59:59.999999999 1969-12-31 23:59:59.999999999 1970-01-01 00:00:00.000000+08:00 1.96912318E13 19691231235959 +3 1970-01-01 1970-01-01 1970-01-01T00:00 1970-01-01T00:00 1970-01-01T00:00 1970-01-01T00:00 00:00:00 00:00:00.000 00:00:00.000000 19700101000000 19700101000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000+08:00 1.97001006E13 19700101000000 +4 2024-02-29 2024-02-29 2024-02-29T12:34:56 2024-02-29T12:34:56 2024-02-29T12:34:56.123 2024-02-29T12:34:56.123457 12:34:56 12:34:56.123 12:34:56.123457 20240229123456 20240229123456 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123457+08:00 2.02402284E13 20240229123456 +5 2262-04-11 2262-04-11 2262-04-11T23:47:17 2262-04-11T23:47:17 2262-04-11T23:47:16.855 2262-04-11T23:47:16.854776 23:47:17 23:47:16.855 23:47:16.854776 22620411234716 22620411234716 2262-04-11 23:47:16.854775807 2262-04-11 23:47:16.854775807 2262-04-11 23:47:16.854775807 2262-04-11 23:47:16.854775807 2262-04-11 23:47:16.854775807 2262-04-11 23:47:16.854776+08:00 2.26204121E13 22620411234716 +6 \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N + +-- !variant_round_trip -- +1 1677-09-21 00:12:43.145224192 +2 1969-12-31 23:59:59.999999999 +3 1970-01-01 00:00:00.000000000 +4 2024-02-29 12:34:56.123456789 +5 2262-04-11 23:47:16.854775807 +6 \N + +-- !datelike_boundary_non_strict -- +1 \N \N +2 1677-09-21 00:12:43.145225000 1677-09-21 00:12:43.145225000 +3 2262-04-11 23:47:16.854775000 2262-04-11 23:47:16.854775000 +4 \N \N + +-- !datelike_boundary_constants_non_strict -- +\N 1677-09-21 00:12:43.145225000 2262-04-11 23:47:16.854775000 \N \N 1677-09-21 00:12:43.145225000 2262-04-11 23:47:16.854775000 \N + +-- !fraction_discard_and_carry -- +1677-09-21T00:12:43.145224 1969-12-31T23:59:59.999999 1970-01-01T00:00 2262-04-11T23:47:16.854776 + +-- !fraction_discard_and_carry_timestamptz -- +1677-09-21 00:12:43.145224+08:00 1969-12-31 23:59:59.999999+08:00 1970-01-01 00:00:00.000000+08:00 2262-04-11 23:47:16.854776+08:00 + diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_complex_type.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_complex_type.out new file mode 100644 index 00000000000000..5f32ab26fd2cad --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_complex_type.out @@ -0,0 +1,7 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !complex_storage -- +1 ["1677-09-21 00:12:43.145224192", "1970-01-01 00:00:00.123456789", "2262-04-11 23:47:16.854775807"] {"before":"1969-12-31 23:59:59.999999999", "after":"1970-01-01 00:00:00.000000001"} {"minimum":"1677-09-21 00:12:43.145224192", "maximum":"2262-04-11 23:47:16.854775807"} {"dt":"1970-01-01 00:00:00.123456789"} +2 \N \N \N \N + +-- !json_round_trip -- +1970-01-01 00:00:00.123456789 diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_count_distinct.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_count_distinct.out new file mode 100644 index 00000000000000..3af9e8e0027d08 --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_count_distinct.out @@ -0,0 +1,6 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !count -- +6 5 + +-- !count_distinct -- +4 4 4 diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_delete.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_delete.out new file mode 100644 index 00000000000000..a244d685c43202 --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_delete.out @@ -0,0 +1,20 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !before -- +1677-09-21 00:12:43.145224192 1 minimum +1969-12-31 23:59:59.999999999 2 before +1970-01-01 00:00:00.000000000 3 epoch +1970-01-01 00:00:00.000000001 4 after +2262-04-11 23:47:16.854775807 5 maximum + +-- !after_eq -- +1677-09-21 00:12:43.145224192 1 minimum +1970-01-01 00:00:00.000000000 3 epoch +1970-01-01 00:00:00.000000001 4 after +2262-04-11 23:47:16.854775807 5 maximum + +-- !after_in -- +1970-01-01 00:00:00.000000000 3 epoch +1970-01-01 00:00:00.000000001 4 after + +-- !after_range -- +1970-01-01 00:00:00.000000000 3 epoch diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_expressions.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_expressions.out new file mode 100644 index 00000000000000..1674831a68a4ef --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_expressions.out @@ -0,0 +1,96 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !comparisons -- +1 false true false false true true false +2 false true false false true true false +3 false true false false true true false +4 \N \N \N \N \N \N false +5 true false false true false true true +6 \N \N \N \N \N \N false +7 \N \N \N \N \N \N true + +-- !null_predicates -- +1 false true +2 false true +3 false true +4 false true +5 false true +6 true false +7 true false + +-- !in_not_in -- +1 true false \N \N +2 false true \N \N +3 true false true false +4 false true \N \N +5 false true \N \N +6 \N \N \N \N +7 \N \N \N \N + +-- !between -- +1 false true +2 true false +3 true false +4 true false +5 false true +6 \N \N +7 \N \N + +-- !boolean_composition -- +1 false true true +2 false true true +3 true true true +4 true true false +5 true false true +6 true true false +7 true false false + +-- !condition_result -- +1 1970-01-01 00:00:00.000000000 1677-09-21 00:12:43.145224192 1677-09-21 00:12:43.145224192 1677-09-21 00:12:43.145224192 1677-09-21 00:12:43.145224192 +2 1969-12-31 23:59:59.999999999 1969-12-31 23:59:59.999999999 1969-12-31 23:59:59.999999999 1969-12-31 23:59:59.999999999 1970-01-01 00:00:00.000000001 +3 2024-02-29 12:34:56.123456789 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000001 +4 1970-01-01 00:00:00.000000001 1970-01-01 00:00:00.000000001 1970-01-01 00:00:00.000000001 1970-01-01 00:00:00.000000001 \N +5 2262-04-11 23:47:16.854775807 2262-04-11 23:47:16.854775807 2262-04-11 23:47:16.854775807 \N \N +6 \N 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 \N \N +7 \N \N 1970-01-01 00:00:00.000000000 \N \N + +-- !mixed_condition_result -- +1 2024-02-29 12:34:56.123456000 2024-02-29 12:34:56.123456000 +2 1969-12-31 23:59:59.999999999 1969-12-31 23:59:59.999999999 +3 2024-02-29 12:34:56.123456000 2024-02-29 12:34:56.123456000 +4 1970-01-01 00:00:00.000000001 1970-01-01 00:00:00.000000001 +5 2024-02-29 12:34:56.123456000 2024-02-29 12:34:56.123456000 +6 \N \N +7 2024-02-29 12:34:56.123456000 2024-02-29 12:34:56.123456000 + +-- !mixed_temporal_comparisons -- +1 false true true true false false false false true true true false false false +2 true false false true false true true true false false true false true true +3 \N \N \N \N \N \N false \N \N \N \N \N \N false + +-- !mixed_temporal_in -- +1 false true +2 true false +3 \N \N + +-- !mixed_time_comparisons -- +true true + +-- !mixed_temporal_conditions -- +1 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 12:34:56.123457 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 12:34:56.123457 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 12:34:56.123457 +2 2024-02-29 12:34:56.123456000 2024-02-29 12:34:56.123456000 12:34:56.123456 2024-02-29 12:34:56.123456000 2024-02-29 12:34:56.123456000 12:34:56.123456 2024-02-29 12:34:56.123456000 \N \N 2024-02-29 12:34:56.123456000 12:34:56.123456 +3 2024-02-29 12:34:56.123456000 2024-02-29 12:34:56.123456000 12:34:56.123456 2024-02-29 12:34:56.123456000 2024-02-29 12:34:56.123456000 12:34:56.123456 2024-02-29 12:34:56.123456000 \N \N 2024-02-29 12:34:56.123456000 12:34:56.123456 + +-- !mixed_temporal_functions -- +1 0 00:00:00.000000 0 0 00:00:00.000000 0 0 +2 0 00:00:00.000000 0 0 00:00:00.000000 0 1 +3 \N \N \N \N \N \N \N + +-- !mixed_temporal_constants -- +true true true 2024-02-29 12:34:56.123456789 2024-02-29 12:34:56.123456789 12:34:56.123456 2024-02-29 12:34:56.123456000 2024-02-29 12:34:56.123456000 2024-02-29 12:34:56.123456789 0 00:00:00.000000 0 + +-- !folded_conditions -- +1970-01-01 00:00:00.000000001 1970-01-01 00:00:00.000000001 true + +-- !runtime_conditions -- +1970-01-01 00:00:00.000000001 1970-01-01 00:00:00.000000001 true + diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_functions.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_functions.out new file mode 100644 index 00000000000000..5a2df95b91bd7f --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_functions.out @@ -0,0 +1,126 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !scalar_functions_fold -- +2024 2024-02-29 12:34:56.123456 12:34:56.123456 1970-01-01 00:00:00.999999999 00:00:01.123456 2024-02-29 12:34:56.000000000 2024-02-29 12:34:56.000000000 2024-02-29 12:34:57.000000000 2024-02-29 04:34:56.123456789 ["1969-12-31 23:59:59.000000001", "1970-01-01 00:00:00.000000001", "1970-01-01 00:00:01.000000001"] + +-- !scalar_functions_runtime -- +2024 2024-02-29 12:34:56.123456 12:34:56.123456 1970-01-01 00:00:00.999999999 00:00:01.123456 2024-02-29 12:34:56.000000000 2024-02-29 12:34:56.000000000 2024-02-29 12:34:57.000000000 2024-02-29 04:34:56.123456789 ["1969-12-31 23:59:59.000000001", "1970-01-01 00:00:00.000000001", "1970-01-01 00:00:01.000000001"] + +-- !timezone_inputs -- +2024 2024 2024 1970-01-01 00:00:00.999999999 1970-01-01 00:00:00.999999999 1970-01-01 00:00:00.999999999 + +-- !nanosecond_boundaries -- +23:59:59.999999 23:59:59.999999 1677-09-21 00:12:43.145224 00:00:00.000000 0 1970-01-01 00:00:00.000000500 + +-- !extract_calendar -- +1 1677 17 3 9 21 21 3 264 1 38 38 38 167738 167738 Tuesday September +2 1969 20 4 12 31 31 4 365 2 52 1 1 196952 197001 Wednesday December +3 1970 20 1 1 1 1 5 1 3 0 1 1 196952 197001 Thursday January +4 1970 20 1 1 1 1 5 1 3 0 1 1 196952 197001 Thursday January +5 2024 21 1 2 29 29 5 60 3 8 9 9 202408 202409 Thursday February +6 2262 23 2 4 11 11 6 101 4 14 15 15 226214 226215 Friday April +7 \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N + +-- !extract_time -- +1 0 12 43 145224 1677-09 21 00 21 00:12 21 00:12:43 21 00:12:43.145224 00:12 00:12:43 00:12:43.145224 12:43 12:43.145224 43.145224 +2 23 59 59 999999 1969-12 31 23 31 23:59 31 23:59:59 31 23:59:59.999999 23:59 23:59:59 23:59:59.999999 59:59 59:59.999999 59.999999 +3 0 0 0 0 1970-01 01 00 01 00:00 01 00:00:00 01 00:00:00.000000 00:00 00:00:00 00:00:00.000000 00:00 00:00.000000 00.000000 +4 0 0 0 0 1970-01 01 00 01 00:00 01 00:00:00 01 00:00:00.000000 00:00 00:00:00 00:00:00.000000 00:00 00:00.000000 00.000000 +5 12 34 56 123456 2024-02 29 12 29 12:34 29 12:34:56 29 12:34:56.123456 12:34 12:34:56 12:34:56.123456 34:56 34:56.123456 56.123456 +6 23 47 16 854775 2262-04 11 23 11 23:47 11 23:47:16 11 23:47:16.854775 23:47 23:47:16 23:47:16.854775 47:16 47:16.854775 16.854775 +7 \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N + +-- !format_and_convert -- +1 1677-09-21 00:12:43.145224 00:12:43.145224 1677-09-21T00:12:43.145224192 1677-09-21 00:12:43.145224192 1677-09-21 1677-09-21 1677-09-21 1677-09-21 1677-09-21 00:12:43.145224192 00:12:43.145224 612776 52943847163 0E-9 -9223400837 -9223400836855 -9223400836854776 1677-09-30 1677-09-20 +2 1969-12-31 23:59:59.999999 23:59:59.999999 1969-12-31T23:59:59.999999999 1969-12-31 23:59:59.999999999 1969-12-31 1969-12-31 1969-12-31 1969-12-31 1969-12-31 23:59:59.999999999 23:59:59.999999 719527 62167219199 0E-9 -28801 -28800001 -28800000001 1969-12-31 1969-12-29 +3 1970-01-01 00:00:00.000000 00:00:00.000000 1970-01-01T00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 1970-01-01 1970-01-01 1970-01-01 1970-01-01 00:00:00.000000000 00:00:00.000000 719528 62167219200 0E-9 -28800 -28800000 -28800000000 1970-01-31 1970-01-01 +4 1970-01-01 00:00:00.000000 00:00:00.000000 1970-01-01T00:00:00.000000001 1970-01-01 00:00:00.000000001 1970-01-01 1970-01-01 1970-01-01 1970-01-01 1970-01-01 00:00:00.000000001 00:00:00.000000 719528 62167219200 0E-9 -28800 -28800000 -28800000000 1970-01-31 1970-01-01 +5 2024-02-29 12:34:56.123456 12:34:56.123456 2024-02-29T12:34:56.123456789 2024-02-29 12:34:56.123456789 2024-02-29 2024-02-29 2024-02-29 2024-02-29 2024-02-29 12:34:56.123456789 12:34:56.123456 739310 63876429296 1709181296.123456789 1709181296 1709181296123 1709181296123456 2024-02-29 2024-02-26 +6 2262-04-11 23:47:16.854775 23:47:16.854775 2262-04-11T23:47:16.854775807 2262-04-11 23:47:16.854775807 2262-04-11 2262-04-11 2262-04-11 2262-04-11 2262-04-11 23:47:16.854775807 23:47:16.854775 826279 71390591236 9223343236.854775807 9223343236 9223343236854 9223343236854775 2262-04-30 2262-04-07 +7 \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N + +-- !simple_add_sub -- +2 1970-01-01 00:00:00.000000999 1969-12-31 23:59:59.999998999 1970-01-01 00:00:00.000999999 1969-12-31 23:59:59.998999999 1970-01-01 00:00:00.999999999 1969-12-31 23:59:58.999999999 1970-01-01 00:00:59.999999999 1969-12-31 23:58:59.999999999 1970-01-01 00:59:59.999999999 1969-12-31 22:59:59.999999999 1970-01-01 23:59:59.999999999 1969-12-30 23:59:59.999999999 1970-01-07 23:59:59.999999999 1969-12-24 23:59:59.999999999 1970-01-31 23:59:59.999999999 1969-11-30 23:59:59.999999999 1970-03-31 23:59:59.999999999 1969-09-30 23:59:59.999999999 1970-12-31 23:59:59.999999999 1968-12-31 23:59:59.999999999 +3 1970-01-01 00:00:00.000001000 1969-12-31 23:59:59.999999000 1970-01-01 00:00:00.001000000 1969-12-31 23:59:59.999000000 1970-01-01 00:00:01.000000000 1969-12-31 23:59:59.000000000 1970-01-01 00:01:00.000000000 1969-12-31 23:59:00.000000000 1970-01-01 01:00:00.000000000 1969-12-31 23:00:00.000000000 1970-01-02 00:00:00.000000000 1969-12-31 00:00:00.000000000 1970-01-08 00:00:00.000000000 1969-12-25 00:00:00.000000000 1970-02-01 00:00:00.000000000 1969-12-01 00:00:00.000000000 1970-04-01 00:00:00.000000000 1969-10-01 00:00:00.000000000 1971-01-01 00:00:00.000000000 1969-01-01 00:00:00.000000000 +4 1970-01-01 00:00:00.000001001 1969-12-31 23:59:59.999999001 1970-01-01 00:00:00.001000001 1969-12-31 23:59:59.999000001 1970-01-01 00:00:01.000000001 1969-12-31 23:59:59.000000001 1970-01-01 00:01:00.000000001 1969-12-31 23:59:00.000000001 1970-01-01 01:00:00.000000001 1969-12-31 23:00:00.000000001 1970-01-02 00:00:00.000000001 1969-12-31 00:00:00.000000001 1970-01-08 00:00:00.000000001 1969-12-25 00:00:00.000000001 1970-02-01 00:00:00.000000001 1969-12-01 00:00:00.000000001 1970-04-01 00:00:00.000000001 1969-10-01 00:00:00.000000001 1971-01-01 00:00:00.000000001 1969-01-01 00:00:00.000000001 +5 2024-02-29 12:34:56.123457789 2024-02-29 12:34:56.123455789 2024-02-29 12:34:56.124456789 2024-02-29 12:34:56.122456789 2024-02-29 12:34:57.123456789 2024-02-29 12:34:55.123456789 2024-02-29 12:35:56.123456789 2024-02-29 12:33:56.123456789 2024-02-29 13:34:56.123456789 2024-02-29 11:34:56.123456789 2024-03-01 12:34:56.123456789 2024-02-28 12:34:56.123456789 2024-03-07 12:34:56.123456789 2024-02-22 12:34:56.123456789 2024-03-29 12:34:56.123456789 2024-01-29 12:34:56.123456789 2024-05-29 12:34:56.123456789 2023-11-29 12:34:56.123456789 2025-02-28 12:34:56.123456789 2023-02-28 12:34:56.123456789 + +-- !compound_add_sub -- +5 2024-03-01 14:34:56.123456789 2024-02-28 10:34:56.123456789 2024-03-01 14:37:56.123456789 2024-02-28 10:31:56.123456789 2024-03-01 14:38:00.123456789 2024-02-28 10:31:52.123456789 2024-03-01 14:38:00.123461789 2024-02-28 10:31:52.123451789 2024-02-29 14:37:56.123456789 2024-02-29 10:31:56.123456789 2024-02-29 14:38:00.123456789 2024-02-29 10:31:52.123456789 2024-02-29 14:38:00.123461789 2024-02-29 10:31:52.123451789 2024-02-29 12:38:00.123456789 2024-02-29 12:31:52.123456789 2024-02-29 12:38:00.123461789 2024-02-29 12:31:52.123451789 2024-02-29 12:35:00.123461789 2024-02-29 12:34:52.123451789 2025-04-29 12:34:56.123456789 2022-12-29 12:34:56.123456789 + +-- !add_time_sub_time -- +2 1970-01-01 01:02:03.123455999 1969-12-31 22:57:56.876543999 +3 1970-01-01 01:02:03.123456000 1969-12-31 22:57:56.876544000 +4 1970-01-01 01:02:03.123456001 1969-12-31 22:57:56.876544001 +5 2024-02-29 13:36:59.246912789 2024-02-29 11:32:53.000000789 + +-- !diff_units -- +00:00:01.123456 1 1 1 1 1 1 1 1 1 0 1 + +-- !trunc -- +2 1969-01-01 00:00:00.000000000 1969-10-01 00:00:00.000000000 1969-12-01 00:00:00.000000000 1969-12-29 00:00:00.000000000 1969-12-31 00:00:00.000000000 1969-12-31 23:00:00.000000000 1969-12-31 23:59:00.000000000 1969-12-31 23:59:59.000000000 +3 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1969-12-29 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 +4 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1969-12-29 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 +5 2024-01-01 00:00:00.000000000 2024-01-01 00:00:00.000000000 2024-02-01 00:00:00.000000000 2024-02-26 00:00:00.000000000 2024-02-29 00:00:00.000000000 2024-02-29 12:00:00.000000000 2024-02-29 12:34:00.000000000 2024-02-29 12:34:56.000000000 + +-- !floor -- +2 1969-01-01 00:00:00.000000000 1969-10-01 00:00:00.000000000 1969-12-01 00:00:00.000000000 1969-12-29 00:00:00.000000000 1969-12-31 00:00:00.000000000 1969-12-31 23:00:00.000000000 1969-12-31 23:59:00.000000000 1969-12-31 23:59:59.000000000 +3 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1969-12-29 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 +4 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1969-12-29 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 +5 2024-01-01 00:00:00.000000000 2024-01-01 00:00:00.000000000 2024-02-01 00:00:00.000000000 2024-02-26 00:00:00.000000000 2024-02-29 00:00:00.000000000 2024-02-29 12:00:00.000000000 2024-02-29 12:34:00.000000000 2024-02-29 12:34:56.000000000 + +-- !ceil -- +2 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-05 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 +3 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-05 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 +4 1971-01-01 00:00:00.000000000 1970-04-01 00:00:00.000000000 1970-02-01 00:00:00.000000000 1970-01-05 00:00:00.000000000 1970-01-02 00:00:00.000000000 1970-01-01 01:00:00.000000000 1970-01-01 00:01:00.000000000 1970-01-01 00:00:01.000000000 +5 2025-01-01 00:00:00.000000000 2024-04-01 00:00:00.000000000 2024-03-01 00:00:00.000000000 2024-03-04 00:00:00.000000000 2024-03-01 00:00:00.000000000 2024-02-29 13:00:00.000000000 2024-02-29 12:35:00.000000000 2024-02-29 12:34:57.000000000 + +-- !floor_ceil_period_origin -- +1970-01-01 00:00:02.000000000 1970-01-01 00:00:04.000000000 1970-01-01 00:00:01.500000000 1970-01-01 00:00:02.500000000 + +-- !date_floor_ceil_interval_constants -- +1969-12-31 23:59:55.000000000 1970-01-01 00:00:00.000000000 2024-02-29 12:33:00.000000000 2024-02-29 12:36:00.000000000 + +-- !date_floor_ceil_interval_columns -- +2 1969-12-31 23:59:55.000000000 1970-01-01 00:00:00.000000000 +3 1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 +4 1970-01-01 00:00:00.000000000 1970-01-01 00:00:05.000000000 +5 2024-02-29 12:34:55.000000000 2024-02-29 12:35:00.000000000 + +-- !sequence_second -- +["1969-12-31 23:59:58.000000001", "1969-12-31 23:59:59.000000001", "1970-01-01 00:00:00.000000001", "1970-01-01 00:00:01.000000001"] + +-- !sequence_month -- +["2024-01-31 12:34:56.123456789", "2024-02-29 12:34:56.123456789", "2024-03-29 12:34:56.123456789"] + +-- !sequence_all_units -- +["2024-02-29 12:34:56.123456789", "2025-02-28 12:34:56.123456789"] ["2024-02-29 12:34:56.123456789", "2024-05-29 12:34:56.123456789", "2024-08-29 12:34:56.123456789"] ["2024-02-29 12:34:56.123456789", "2024-03-07 12:34:56.123456789", "2024-03-14 12:34:56.123456789"] ["2024-02-29 12:34:56.123456789", "2024-03-01 12:34:56.123456789", "2024-03-02 12:34:56.123456789"] ["2024-02-29 22:34:56.123456789", "2024-02-29 23:34:56.123456789", "2024-03-01 00:34:56.123456789", "2024-03-01 01:34:56.123456789"] ["1969-12-31 23:58:56.123456789", "1969-12-31 23:59:56.123456789", "1970-01-01 00:00:56.123456789", "1970-01-01 00:01:56.123456789"] ["1969-12-31 00:00:00.000000001", "1970-01-01 00:00:00.000000001"] + +-- !convert_tz -- +2024-02-29 04:34:56.123456789 + +-- !comparison_helpers -- +1969-12-31 23:59:59.999999999 1970-01-01 00:00:00.000000001 2 + +-- !aggregate_helpers -- +1677-09-21 00:12:43.145224192 2262-04-11 23:47:16.854775807 1677-09-21 00:12:43.145224192 2262-04-11 23:47:16.854775807 + +-- !additional_supported_aggregates -- +["1677-09-21 00:12:43.145224192", "1969-12-31 23:59:59.999999999", "1970-01-01 00:00:00.000000000", "1970-01-01 00:00:00.000000001", "2024-02-29 12:34:56.123456789", "2262-04-11 23:47:16.854775807"] ["1677-09-21 00:12:43.145224192", "1969-12-31 23:59:59.999999999", "1970-01-01 00:00:00.000000000", "1970-01-01 00:00:00.000000001", "2024-02-29 12:34:56.123456789", "2262-04-11 23:47:16.854775807"] ["1677-09-21 00:12:43.145224192", "1969-12-31 23:59:59.999999999", "1970-01-01 00:00:00.000000000", "1970-01-01 00:00:00.000000001", "2024-02-29 12:34:56.123456789", "2262-04-11 23:47:16.854775807"] {"num_buckets":6,"buckets":[{"lower":"1677-09-21 00:12:43.145224192","upper":"1677-09-21 00:12:43.145224192","ndv":1,"count":1,"pre_sum":0},{"lower":"1969-12-31 23:59:59.999999999","upper":"1969-12-31 23:59:59.999999999","ndv":1,"count":1,"pre_sum":1},{"lower":"1970-01-01 00:00:00.000000000","upper":"1970-01-01 00:00:00.000000000","ndv":1,"count":1,"pre_sum":2},{"lower":"1970-01-01 00:00:00.000000001","upper":"1970-01-01 00:00:00.000000001","ndv":1,"count":1,"pre_sum":3},{"lower":"2024-02-29 12:34:56.123456789","upper":"2024-02-29 12:34:56.123456789","ndv":1,"count":1,"pre_sum":4},{"lower":"2262-04-11 23:47:16.854775807","upper":"2262-04-11 23:47:16.854775807","ndv":1,"count":1,"pre_sum":5}]} ["2262-04-11 23:47:16.854775807", "2024-02-29 12:34:56.123456789", "1970-01-01 00:00:00.000000001"] ["1677-09-21 00:12:43.145224192", "1969-12-31 23:59:59.999999999", "1970-01-01 00:00:00.000000000", "1970-01-01 00:00:00.000000001", "2024-02-29 12:34:56.123456789", "2262-04-11 23:47:16.854775807"] ["1677-09-21 00:12:43.145224192", "1969-12-31 23:59:59.999999999", "1970-01-01 00:00:00.000000000", "1970-01-01 00:00:00.000000001", "2024-02-29 12:34:56.123456789", "2262-04-11 23:47:16.854775807"] + +-- !event_aggregates -- +1 true 2 2 ["2262-04-11 23:47:16.854775807", "2024-02-29 12:34:56.123456789", "1970-01-01 00:00:00.000000001"] + +-- !array_and_map_functions -- +1677-09-21 00:12:43.145224192 2262-04-11 23:47:16.854775807 true 2 2 true true true + +-- !dictionary_functions -- +1677-09-21 00:12:43.145224192 1970-01-01 00:00:00.000000000 {"value":"2024-02-29 12:34:56.123456789"} + +-- !window_functions -- +1 \N 1969-12-31 23:59:59.999999999 1677-09-21 00:12:43.145224192 \N +2 1677-09-21 00:12:43.145224192 1970-01-01 00:00:00.000000000 1677-09-21 00:12:43.145224192 \N +3 1969-12-31 23:59:59.999999999 1970-01-01 00:00:00.000000001 1677-09-21 00:12:43.145224192 \N +4 1970-01-01 00:00:00.000000000 2024-02-29 12:34:56.123456789 1677-09-21 00:12:43.145224192 \N +5 1970-01-01 00:00:00.000000001 2262-04-11 23:47:16.854775807 1677-09-21 00:12:43.145224192 \N +6 2024-02-29 12:34:56.123456789 \N 1677-09-21 00:12:43.145224192 \N +7 2262-04-11 23:47:16.854775807 \N 1677-09-21 00:12:43.145224192 \N diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_generated_column.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_generated_column.out new file mode 100644 index 00000000000000..b2aa46612bdbb3 --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_generated_column.out @@ -0,0 +1,5 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !generated_column -- +1 1677-09-21 00:12:43.145224192 1677-09-21 00:12:43.145224192 true +2 1970-01-01 00:00:00.123456789 1970-01-01 00:00:00.123456789 true +3 2262-04-11 23:47:16.854775807 2262-04-11 23:47:16.854775807 true diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_group_by.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_group_by.out new file mode 100644 index 00000000000000..9bd795dcdbe0c1 --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_group_by.out @@ -0,0 +1,6 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !group_by -- +\N 2 5 6 +1677-09-21 00:12:43.145224192 1 1 1 +1970-01-01 00:00:00.000000000 2 2 3 +2262-04-11 23:47:16.854775807 1 4 4 diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_index.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_index.out new file mode 100644 index 00000000000000..93c37d29c9abef --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_index.out @@ -0,0 +1,11 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !eq -- +3 1970-01-01 00:00:00.000000001 + +-- !range -- +2 1970-01-01 00:00:00.000000000 +3 1970-01-01 00:00:00.000000001 + +-- !in -- +1 1677-09-21 00:12:43.145224192 +4 2262-04-11 23:47:16.854775807 diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_join.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_join.out new file mode 100644 index 00000000000000..aea1951253c384 --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_join.out @@ -0,0 +1,10 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !inner_join -- +1 1677-09-21 00:12:43.145224192 11 +3 1970-01-01 00:00:00.000000001 12 + +-- !left_join -- +1 1677-09-21 00:12:43.145224192 11 +2 1970-01-01 00:00:00.000000000 \N +3 1970-01-01 00:00:00.000000001 12 +4 \N \N diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_literal.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_literal.out new file mode 100644 index 00000000000000..927c6c26d58c40 --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_literal.out @@ -0,0 +1,23 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !boundary_and_rounding -- +1677-09-21 00:12:43.145224192 1969-12-31 23:59:59.999999999 1970-01-01 00:00:00.123456789 1970-01-01 00:00:00.123456790 1970-01-01 00:00:01.000000000 2262-04-11 23:47:16.854775807 + +-- !boundary_and_rounding_without_fold -- +1677-09-21 00:12:43.145224192 1970-01-01 00:00:00.123456790 1970-01-01 00:00:01.000000000 2262-04-11 23:47:16.854775807 + +-- !invalid_and_out_of_range -- +\N \N \N + +-- !nonconstant_permissive_cast -- +1 2024-01-01 00:00:00.123456789 +2 \N + +-- !seconds_add -- +1970-01-01 00:00:01.000000001 + +-- !current_timestamp_support -- +true true + +-- !timestamp_ns_defaults -- +1 1970-01-01 00:00:00.000000001 true true true true true +2 1970-01-01 00:00:00.000000001 true true true true true diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_mv.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_mv.out new file mode 100644 index 00000000000000..fd92b20011f87a --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_mv.out @@ -0,0 +1,10 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !sync_mv -- +\N 1 +1677-09-21 00:12:43.145224192 1 +1970-01-01 00:00:00.000000000 2 +2262-04-11 23:47:16.854775807 1 + +-- !multi_table_mv -- +1 1677-09-21 00:12:43.145224192 11 +4 2262-04-11 23:47:16.854775807 12 diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_partition_bucket.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_partition_bucket.out new file mode 100644 index 00000000000000..b50d24e2867472 --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_partition_bucket.out @@ -0,0 +1,16 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !partition_rows -- +1 1677-09-21 00:12:43.145224192 +2 1969-12-31 23:59:59.999999999 +3 1970-01-01 00:00:00.000000000 +4 1970-01-01 00:00:00.000000001 +5 1970-01-01 00:00:00.123456789 +6 2262-04-11 23:47:16.854775807 +7 \N + +-- !nullable_first_range -- +7 \N + +-- !list_partition_rounding -- +1970-01-01 00:00:00.123456790 1 +1970-01-01 00:00:01.000000000 2 diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_primary_key.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_primary_key.out new file mode 100644 index 00000000000000..5e594084c5667e --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_primary_key.out @@ -0,0 +1,11 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !key_range_scan -- +1969-12-31 23:59:59.999999999 2 before +1970-01-01 00:00:00.000000000 3 epoch + +-- !full_key_lookup -- +1970-01-01 00:00:00.000000001 4 after + +-- !timestamp_ns_sequence_type -- +1 newer 1970-01-01 00:00:00.000000001 +2 maximum 2262-04-11 23:47:16.854775807 diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_rf.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_rf.out new file mode 100644 index 00000000000000..240599bd1dd375 --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_rf.out @@ -0,0 +1,15 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !runtime_filter_in -- +1 1677-09-21 00:12:43.145224192 11 +4 1970-01-01 00:00:00.000000001 12 +5 2262-04-11 23:47:16.854775807 13 + +-- !runtime_filter_bloom -- +1 1677-09-21 00:12:43.145224192 11 +4 1970-01-01 00:00:00.000000001 12 +5 2262-04-11 23:47:16.854775807 13 + +-- !runtime_filter_min_max -- +1 1677-09-21 00:12:43.145224192 11 +4 1970-01-01 00:00:00.000000001 12 +5 2262-04-11 23:47:16.854775807 13 diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_sort.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_sort.out new file mode 100644 index 00000000000000..8a26c6648b6e7f --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_sort.out @@ -0,0 +1,25 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !asc -- +1 2262-04-11 23:47:16.854775807 +2 1970-01-01 00:00:00.000000001 +3 \N +4 1677-09-21 00:12:43.145224192 +5 1970-01-01 00:00:00.000000000 +6 1969-12-31 23:59:59.999999999 + +-- !desc -- +1 2262-04-11 23:47:16.854775807 +2 1970-01-01 00:00:00.000000001 +3 \N +4 1677-09-21 00:12:43.145224192 +5 1970-01-01 00:00:00.000000000 +6 1969-12-31 23:59:59.999999999 + +-- !topn -- +4 1677-09-21 00:12:43.145224192 +5 1970-01-01 00:00:00.000000000 +6 1969-12-31 23:59:59.999999999 + +-- !topn_offset -- +2 1970-01-01 00:00:00.000000001 +5 1970-01-01 00:00:00.000000000 diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_storage_agg_key.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_storage_agg_key.out new file mode 100644 index 00000000000000..e65a981e2ade3c --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_storage_agg_key.out @@ -0,0 +1,38 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !all -- +1677-09-21 00:12:43.145224192 1677-09-21 00:12:43.145224192 1677-09-21 00:12:43.145224200 1 +1970-01-01 00:00:00.000000000 2262-04-11 23:47:16.854775807 1969-12-31 23:59:59.999999999 5 +2262-04-11 23:47:16.854775807 2262-04-11 23:47:16.854775807 2262-04-11 23:47:16.854775800 4 + +-- !eq -- +1970-01-01 00:00:00.000000000 5 + +-- !ne -- +1677-09-21 00:12:43.145224192 1 +2262-04-11 23:47:16.854775807 4 + +-- !gt -- +2262-04-11 23:47:16.854775807 4 + +-- !ge -- +1970-01-01 00:00:00.000000000 5 +2262-04-11 23:47:16.854775807 4 + +-- !lt -- +1677-09-21 00:12:43.145224192 1 + +-- !le -- +1677-09-21 00:12:43.145224192 1 +1970-01-01 00:00:00.000000000 5 + +-- !in -- +1677-09-21 00:12:43.145224192 1 +2262-04-11 23:47:16.854775807 4 + +-- !not_in -- +1970-01-01 00:00:00.000000000 5 + +-- !is_not_null -- +1677-09-21 00:12:43.145224192 +1970-01-01 00:00:00.000000000 +2262-04-11 23:47:16.854775807 diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_storage_dup_key.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_storage_dup_key.out new file mode 100644 index 00000000000000..19231cb637b53e --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_storage_dup_key.out @@ -0,0 +1,80 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !all -- +\N \N 6 +1677-09-21 00:12:43.145224192 1677-09-21 00:12:43.145224200 1 +1969-12-31 23:59:59.999999999 1969-12-31 23:59:59.999999990 2 +1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000000 3 +1970-01-01 00:00:00.000000001 1970-01-01 00:00:00.123456789 4 +2262-04-11 23:47:16.854775807 2262-04-11 23:47:16.854775800 5 + +-- !eq -- +3 + +-- !ne -- +1 +2 +4 +5 + +-- !gt -- +4 +5 + +-- !ge -- +3 +4 +5 + +-- !lt -- +1 +2 + +-- !le -- +1 +2 +3 + +-- !in -- +1 +5 + +-- !not_in -- +2 +3 +4 + +-- !is_null -- +6 + +-- !is_not_null -- +1 +2 +3 +4 +5 + +-- !min_max_count -- +1677-09-21 00:12:43.145224192 2262-04-11 23:47:16.854775807 5 + +-- !cast_datetimev2_6 -- +1 1677-09-21T00:12:43.145224 +2 1970-01-01T00:00 +3 1970-01-01T00:00 +4 1970-01-01T00:00 +5 2262-04-11T23:47:16.854776 +6 \N + +-- !row_store -- +1 1677-09-21 00:12:43.145224192 +2 1970-01-01 00:00:00.123456789 +3 2262-04-11 23:47:16.854775807 + +-- !schema_change_default -- +1 1970-01-01 00:00:00.000000001 +3 1970-01-01 00:00:00.000000001 +6 1970-01-01 00:00:00.000000001 + +-- !invalid_values -- +100 \N \N +101 \N \N +102 \N \N diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_storage_uniq_key.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_storage_uniq_key.out new file mode 100644 index 00000000000000..4c5af9e9c56e7e --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_storage_uniq_key.out @@ -0,0 +1,43 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !all -- +1677-09-21 00:12:43.145224192 1677-09-21 00:12:43.145224200 1 +1969-12-31 23:59:59.999999999 1969-12-31 23:59:59.999999990 2 +1970-01-01 00:00:00.000000000 1970-01-01 00:00:00.000000001 30 +1970-01-01 00:00:00.000000001 1970-01-01 00:00:00.123456789 4 +2262-04-11 23:47:16.854775807 2262-04-11 23:47:16.854775800 5 + +-- !eq -- +30 + +-- !ne -- +1 +2 +4 +5 + +-- !gt -- +4 +5 + +-- !ge -- +30 +4 +5 + +-- !lt -- +1 +2 + +-- !le -- +1 +2 +30 + +-- !in -- +1 +5 + +-- !not_in -- +2 +30 +4 diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_stream_load.csv b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_stream_load.csv new file mode 100644 index 00000000000000..3664e0573775f9 --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_stream_load.csv @@ -0,0 +1,9 @@ +1|1677-09-21 00:12:43.145224192 +2|1969-12-31 23:59:59.999999999 +3|1970-01-01 00:00:00.000000000 +4|1970-01-01 00:00:00.000000001 +5|2262-04-11 23:47:16.854775807 +6|2262-04-11 23:47:16.854775808 +7|1970-02-30 00:00:00.000000000 +8|2023-08-17T01:41:18.123456789Z +9|2023-08-17T01:41:18.123456789America/Los_Angeles diff --git a/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_stream_load.out b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_stream_load.out new file mode 100644 index 00000000000000..85a3a56494a376 --- /dev/null +++ b/regression-test/data/datatype_p0/timestamp_ns/test_timestamp_ns_stream_load.out @@ -0,0 +1,17 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !stream_load -- +1 1677-09-21 00:12:43.145224192 +2 1969-12-31 23:59:59.999999999 +3 1970-01-01 00:00:00.000000000 +4 1970-01-01 00:00:00.000000001 +5 2262-04-11 23:47:16.854775807 +8 2023-08-17 09:41:18.123456789 +9 2023-08-17 16:41:18.123456789 +-- !insert_select -- +1 1677-09-21 00:12:43.145224192 +2 1969-12-31 23:59:59.999999999 +3 1970-01-01 00:00:00.000000000 +4 1970-01-01 00:00:00.000000001 +5 2262-04-11 23:47:16.854775807 +8 2023-08-17 09:41:18.123456789 +9 2023-08-17 16:41:18.123456789 diff --git a/regression-test/data/datatype_p0/timestamptz/test_timestamptz_storage_dup_key.out b/regression-test/data/datatype_p0/timestamptz/test_timestamptz_storage_dup_key.out index 8d0d1946b52bb4..78f2cfbdc7af11 100644 --- a/regression-test/data/datatype_p0/timestamptz/test_timestamptz_storage_dup_key.out +++ b/regression-test/data/datatype_p0/timestamptz/test_timestamptz_storage_dup_key.out @@ -548,6 +548,8 @@ -- !scale_lt0 -- -- !scale_lt1 -- +0000-01-01 08:00:00.000000+08:00 0000-01-01 08:00:00.000000+08:00 0 +0000-01-01 08:00:00.000000+08:00 0000-01-01 08:00:00.000000+08:00 0 -- !scale_lt2 -- 0000-01-01 08:00:00.000000+08:00 0000-01-01 08:00:00.000000+08:00 0 diff --git a/regression-test/data/datatype_p0/timestamptz/test_timestamptz_storage_uniq_key.out b/regression-test/data/datatype_p0/timestamptz/test_timestamptz_storage_uniq_key.out index 34871b633cddea..01e3734e7d68e9 100644 --- a/regression-test/data/datatype_p0/timestamptz/test_timestamptz_storage_uniq_key.out +++ b/regression-test/data/datatype_p0/timestamptz/test_timestamptz_storage_uniq_key.out @@ -388,6 +388,7 @@ -- !scale_lt0 -- -- !scale_lt1 -- +0000-01-01 08:00:00.000000+08:00 3000-01-01 08:00:00.000000+08:00 0 -- !scale_lt2 -- 0000-01-01 08:00:00.000000+08:00 3000-01-01 08:00:00.000000+08:00 0 diff --git a/regression-test/data/external_table_p0/paimon/paimon_timestamp_types.out b/regression-test/data/external_table_p0/paimon/paimon_timestamp_types.out index ddee5b68511e4c..30763d6bac6580 100644 --- a/regression-test/data/external_table_p0/paimon/paimon_timestamp_types.out +++ b/regression-test/data/external_table_p0/paimon/paimon_timestamp_types.out @@ -1,9 +1,9 @@ -- This file is automatically generated. You should know what you did if you want to edit this -- !c1 -- -1 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 +1 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02 10:04:05.123456700 2024-01-02 10:04:05.123456780 2024-01-02 10:04:05.123456789 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 -- !c2 -- -1 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 +1 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02 10:04:05.123456700 2024-01-02 10:04:05.123456780 2024-01-02 10:04:05.123456789 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 -- !ltz_ntz_simple2 -- 1 {"2024-01-01 10:12:34.123456":"2024-01-02 10:12:34.123456", "2024-01-03 10:12:34.123456":"2024-01-04 10:12:34.123456"} {"2024-01-03 10:12:34.123456":"2024-01-04 10:12:34.123456", "2024-01-01 10:12:34.123456":"2024-01-02 10:12:34.123456"} ["2024-01-01 10:12:34.123456", "2024-01-02 10:12:34.123456", "2024-01-03 10:12:34.123456"] ["2024-01-01 10:12:34.123456", "2024-01-02 10:12:34.123456", "2024-01-03 10:12:34.123456"] {"crow1":"2024-01-01 10:12:34.123456", "crow2":"2024-01-02 10:12:34.123456"} @@ -48,10 +48,10 @@ 2024-01-02T10:12:34.123456 -- !c1 -- -1 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123457 2024-01-02T10:04:05.123457 2024-01-02T10:04:05.123457 2024-01-02T02:04:05.100 2024-01-02T02:04:05.120 2024-01-02T02:04:05.123 2024-01-02T02:04:05.123400 2024-01-02T02:04:05.123450 2024-01-02T02:04:05.123456 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 +1 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02 10:04:05.123457000 2024-01-02 10:04:05.123457000 2024-01-02 10:04:05.123457000 2024-01-02T02:04:05.100 2024-01-02T02:04:05.120 2024-01-02T02:04:05.123 2024-01-02T02:04:05.123400 2024-01-02T02:04:05.123450 2024-01-02T02:04:05.123456 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 -- !c2 -- -1 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 +1 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02 10:04:05.123456700 2024-01-02 10:04:05.123456780 2024-01-02 10:04:05.123456789 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123456 -- !ltz_ntz_simple2 -- 1 {"2024-01-01 10:12:34.123456":"2024-01-02 10:12:34.123456", "2024-01-03 10:12:34.123456":"2024-01-04 10:12:34.123456"} {"2024-01-03 02:12:34.123456":"2024-01-04 02:12:34.123456", "2024-01-01 02:12:34.123456":"2024-01-02 02:12:34.123456"} ["2024-01-01 10:12:34.123456", "2024-01-02 10:12:34.123456", "2024-01-03 10:12:34.123456"] ["2024-01-01 02:12:34.123456", "2024-01-02 02:12:34.123456", "2024-01-03 02:12:34.123456"] {"crow1":"2024-01-01 10:12:34.123456", "crow2":"2024-01-02 02:12:34.123456"} diff --git a/regression-test/data/external_table_p0/paimon/test_paimon_minio.out b/regression-test/data/external_table_p0/paimon/test_paimon_minio.out index 78b3edaca1d59f..b610519712df82 100644 --- a/regression-test/data/external_table_p0/paimon/test_paimon_minio.out +++ b/regression-test/data/external_table_p0/paimon/test_paimon_minio.out @@ -3,23 +3,23 @@ 2024-01-02T10:04:05.100 2024-01-02T02:04:05.123457 -- !no_region2 -- -1 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123457 2024-01-02T10:04:05.123457 2024-01-02T10:04:05.123457 2024-01-02T02:04:05.100 2024-01-02T02:04:05.120 2024-01-02T02:04:05.123 2024-01-02T02:04:05.123400 2024-01-02T02:04:05.123450 2024-01-02T02:04:05.123456 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 +1 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02 10:04:05.123457000 2024-01-02 10:04:05.123457000 2024-01-02 10:04:05.123457000 2024-01-02T02:04:05.100 2024-01-02T02:04:05.120 2024-01-02T02:04:05.123 2024-01-02T02:04:05.123400 2024-01-02T02:04:05.123450 2024-01-02T02:04:05.123456 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 -- !region1 -- 2024-01-02T10:04:05.100 2024-01-02T02:04:05.123457 -- !region2 -- -1 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123457 2024-01-02T10:04:05.123457 2024-01-02T10:04:05.123457 2024-01-02T02:04:05.100 2024-01-02T02:04:05.120 2024-01-02T02:04:05.123 2024-01-02T02:04:05.123400 2024-01-02T02:04:05.123450 2024-01-02T02:04:05.123456 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 +1 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02 10:04:05.123457000 2024-01-02 10:04:05.123457000 2024-01-02 10:04:05.123457000 2024-01-02T02:04:05.100 2024-01-02T02:04:05.120 2024-01-02T02:04:05.123 2024-01-02T02:04:05.123400 2024-01-02T02:04:05.123450 2024-01-02T02:04:05.123456 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 -- !no_region1 -- 2024-01-02T10:04:05.100 2024-01-02T02:04:05.123457 -- !no_region2 -- -1 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123457 2024-01-02T10:04:05.123457 2024-01-02T10:04:05.123457 2024-01-02T02:04:05.100 2024-01-02T02:04:05.120 2024-01-02T02:04:05.123 2024-01-02T02:04:05.123400 2024-01-02T02:04:05.123450 2024-01-02T02:04:05.123456 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 +1 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02 10:04:05.123457000 2024-01-02 10:04:05.123457000 2024-01-02 10:04:05.123457000 2024-01-02T02:04:05.100 2024-01-02T02:04:05.120 2024-01-02T02:04:05.123 2024-01-02T02:04:05.123400 2024-01-02T02:04:05.123450 2024-01-02T02:04:05.123456 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 -- !region1 -- 2024-01-02T10:04:05.100 2024-01-02T02:04:05.123457 -- !region2 -- -1 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02T10:04:05.123457 2024-01-02T10:04:05.123457 2024-01-02T10:04:05.123457 2024-01-02T02:04:05.100 2024-01-02T02:04:05.120 2024-01-02T02:04:05.123 2024-01-02T02:04:05.123400 2024-01-02T02:04:05.123450 2024-01-02T02:04:05.123456 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 +1 2024-01-02T10:04:05.100 2024-01-02T10:04:05.120 2024-01-02T10:04:05.123 2024-01-02T10:04:05.123400 2024-01-02T10:04:05.123450 2024-01-02T10:04:05.123456 2024-01-02 10:04:05.123457000 2024-01-02 10:04:05.123457000 2024-01-02 10:04:05.123457000 2024-01-02T02:04:05.100 2024-01-02T02:04:05.120 2024-01-02T02:04:05.123 2024-01-02T02:04:05.123400 2024-01-02T02:04:05.123450 2024-01-02T02:04:05.123456 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 2024-01-02T02:04:05.123457 diff --git a/regression-test/data/external_table_p0/paimon/test_paimon_table_properties.out b/regression-test/data/external_table_p0/paimon/test_paimon_table_properties.out index 0601d62955f4c1..ff9fb5274351fa 100644 --- a/regression-test/data/external_table_p0/paimon/test_paimon_table_properties.out +++ b/regression-test/data/external_table_p0/paimon/test_paimon_table_properties.out @@ -1,4 +1,4 @@ -- This file is automatically generated. You should know what you did if you want to edit this -- !show_create_table -- -ts_scale_orc CREATE TABLE `ts_scale_orc` (\n `id` int NULL,\n `ts1` datetimev2(1) NULL,\n `ts2` datetimev2(2) NULL,\n `ts3` datetimev2(3) NULL,\n `ts4` datetimev2(4) NULL,\n `ts5` datetimev2(5) NULL,\n `ts6` datetimev2(6) NULL,\n `ts7` datetimev2(6) NULL,\n `ts8` datetimev2(6) NULL,\n `ts9` datetimev2(6) NULL,\n `ts11` datetimev2(1) NULL,\n `ts12` datetimev2(2) NULL,\n `ts13` datetimev2(3) NULL,\n `ts14` datetimev2(4) NULL,\n `ts15` datetimev2(5) NULL,\n `ts16` datetimev2(6) NULL,\n `ts17` datetimev2(6) NULL,\n `ts18` datetimev2(6) NULL,\n `ts19` datetimev2(6) NULL\n) ENGINE=paimon\nLOCATION 's3://warehouse/wh/flink_paimon.db/ts_scale_orc'\nPROPERTIES (\n "path" = "s3://warehouse/wh/flink_paimon.db/ts_scale_orc",\n "write-only" = "true",\n "file.format" = "orc"\n); +ts_scale_orc CREATE TABLE `ts_scale_orc` (\n `id` int NULL,\n `ts1` datetimev2(1) NULL,\n `ts2` datetimev2(2) NULL,\n `ts3` datetimev2(3) NULL,\n `ts4` datetimev2(4) NULL,\n `ts5` datetimev2(5) NULL,\n `ts6` datetimev2(6) NULL,\n `ts7` timestamp_ns NULL,\n `ts8` timestamp_ns NULL,\n `ts9` timestamp_ns NULL,\n `ts11` datetimev2(1) NULL,\n `ts12` datetimev2(2) NULL,\n `ts13` datetimev2(3) NULL,\n `ts14` datetimev2(4) NULL,\n `ts15` datetimev2(5) NULL,\n `ts16` datetimev2(6) NULL,\n `ts17` datetimev2(6) NULL,\n `ts18` datetimev2(6) NULL,\n `ts19` datetimev2(6) NULL\n) ENGINE=paimon\nLOCATION 's3://warehouse/wh/flink_paimon.db/ts_scale_orc'\nPROPERTIES (\n "path" = "s3://warehouse/wh/flink_paimon.db/ts_scale_orc",\n "write-only" = "true",\n "file.format" = "orc"\n); diff --git a/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group2.out b/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group2.out index 7b1744aa72f61d..3ab58bf2f754f2 100644 --- a/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group2.out +++ b/regression-test/data/external_table_p0/tvf/test_hdfs_parquet_group2.out @@ -117,9 +117,9 @@ apple_banana_mango9 9.00 -- !test_16 -- -1 Alice 2022-11-16T02:32:09 -2 Bob 2022-11-16T02:32:09 -3 Cecilia 2022-11-16T02:32:09.123534 +1 Alice 2022-11-16 02:32:09.000000002 +2 Bob 2022-11-16 02:32:09.000000003 +3 Cecilia 2022-11-16 02:32:09.123534758 -- !test_17 -- 1001-01-07T09:02:03.123456 1001-01-07T09:02:03.123456 @@ -195,12 +195,12 @@ false 1 2 3 10 1.2 val_1 val_1 HEARTS false 1 2 3 10 1.2 val_1 val_1 HEARTS ["ar false 3 4 5 30 3.2 val_3 val_3 CLUBS \N \N \N \N \N \N \N \N \N ["arr_3", "arr_4", "arr_5"] [3] {3:"val_3", 4:"val_4", 5:"val_5"} {3:[{"nestedintscolumn":[3, 4, 5], "nestedstringcolumn":"val_3"}, {"nestedintscolumn":[4, 5, 6], "nestedstringcolumn":"val_4"}, {"nestedintscolumn":[5, 6, 7], "nestedstringcolumn":"val_5"}], 4:[{"nestedintscolumn":[3, 4, 5], "nestedstringcolumn":"val_3"}, {"nestedintscolumn":[4, 5, 6], "nestedstringcolumn":"val_4"}, {"nestedintscolumn":[5, 6, 7], "nestedstringcolumn":"val_5"}], 5:[{"nestedintscolumn":[3, 4, 5], "nestedstringcolumn":"val_3"}, {"nestedintscolumn":[4, 5, 6], "nestedstringcolumn":"val_4"}, {"nestedintscolumn":[5, 6, 7], "nestedstringcolumn":"val_5"}]} false 5 6 7 50 5.2 val_5 val_5 HEARTS false 5 6 7 50 5.2 val_5 val_5 HEARTS ["arr_5", "arr_6", "arr_7"] [5] {5:"val_5", 6:"val_6", 7:"val_7"} {5:[{"nestedintscolumn":[5, 6, 7], "nestedstringcolumn":"val_5"}, {"nestedintscolumn":[6, 7, 8], "nestedstringcolumn":"val_6"}, {"nestedintscolumn":[7, 8, 9], "nestedstringcolumn":"val_7"}], 6:[{"nestedintscolumn":[5, 6, 7], "nestedstringcolumn":"val_5"}, {"nestedintscolumn":[6, 7, 8], "nestedstringcolumn":"val_6"}, {"nestedintscolumn":[7, 8, 9], "nestedstringcolumn":"val_7"}], 7:[{"nestedintscolumn":[5, 6, 7], "nestedstringcolumn":"val_5"}, {"nestedintscolumn":[6, 7, 8], "nestedstringcolumn":"val_6"}, {"nestedintscolumn":[7, 8, 9], "nestedstringcolumn":"val_7"}]} false 7 8 9 70 7.2 val_7 val_7 CLUBS false 7 8 9 70 7.2 val_7 val_7 CLUBS ["arr_7", "arr_8", "arr_9"] [7] {7:"val_7", 8:"val_8", 9:"val_9"} {7:[{"nestedintscolumn":[7, 8, 9], "nestedstringcolumn":"val_7"}, {"nestedintscolumn":[8, 9, 10], "nestedstringcolumn":"val_8"}, {"nestedintscolumn":[9, 10, 11], "nestedstringcolumn":"val_9"}], 8:[{"nestedintscolumn":[7, 8, 9], "nestedstringcolumn":"val_7"}, {"nestedintscolumn":[8, 9, 10], "nestedstringcolumn":"val_8"}, {"nestedintscolumn":[9, 10, 11], "nestedstringcolumn":"val_9"}], 9:[{"nestedintscolumn":[7, 8, 9], "nestedstringcolumn":"val_7"}, {"nestedintscolumn":[8, 9, 10], "nestedstringcolumn":"val_8"}, {"nestedintscolumn":[9, 10, 11], "nestedstringcolumn":"val_9"}]} -false 9 10 11 90 9.199999999999999 val_9 val_9 HEARTS \N \N \N \N \N \N \N \N \N ["arr_9", "arr_10", "arr_11"] [9] {9:"val_9", 10:"val_10", 11:"val_11"} {9:[{"nestedintscolumn":[9, 10, 11], "nestedstringcolumn":"val_9"}, {"nestedintscolumn":[10, 11, 12], "nestedstringcolumn":"val_10"}, {"nestedintscolumn":[11, 12, 13], "nestedstringcolumn":"val_11"}], 10:[{"nestedintscolumn":[9, 10, 11], "nestedstringcolumn":"val_9"}, {"nestedintscolumn":[10, 11, 12], "nestedstringcolumn":"val_10"}, {"nestedintscolumn":[11, 12, 13], "nestedstringcolumn":"val_11"}], 11:[{"nestedintscolumn":[9, 10, 11], "nestedstringcolumn":"val_9"}, {"nestedintscolumn":[10, 11, 12], "nestedstringcolumn":"val_10"}, {"nestedintscolumn":[11, 12, 13], "nestedstringcolumn":"val_11"}]} +false 9 10 11 90 9.2 val_9 val_9 HEARTS \N \N \N \N \N \N \N \N \N ["arr_9", "arr_10", "arr_11"] [9] {9:"val_9", 10:"val_10", 11:"val_11"} {9:[{"nestedintscolumn":[9, 10, 11], "nestedstringcolumn":"val_9"}, {"nestedintscolumn":[10, 11, 12], "nestedstringcolumn":"val_10"}, {"nestedintscolumn":[11, 12, 13], "nestedstringcolumn":"val_11"}], 10:[{"nestedintscolumn":[9, 10, 11], "nestedstringcolumn":"val_9"}, {"nestedintscolumn":[10, 11, 12], "nestedstringcolumn":"val_10"}, {"nestedintscolumn":[11, 12, 13], "nestedstringcolumn":"val_11"}], 11:[{"nestedintscolumn":[9, 10, 11], "nestedstringcolumn":"val_9"}, {"nestedintscolumn":[10, 11, 12], "nestedstringcolumn":"val_10"}, {"nestedintscolumn":[11, 12, 13], "nestedstringcolumn":"val_11"}]} true 0 1 2 0 0.2 val_0 val_0 SPADES \N \N \N \N \N \N \N \N \N ["arr_0", "arr_1", "arr_2"] [0] {0:"val_0", 1:"val_1", 2:"val_2"} {0:[{"nestedintscolumn":[0, 1, 2], "nestedstringcolumn":"val_0"}, {"nestedintscolumn":[1, 2, 3], "nestedstringcolumn":"val_1"}, {"nestedintscolumn":[2, 3, 4], "nestedstringcolumn":"val_2"}], 1:[{"nestedintscolumn":[0, 1, 2], "nestedstringcolumn":"val_0"}, {"nestedintscolumn":[1, 2, 3], "nestedstringcolumn":"val_1"}, {"nestedintscolumn":[2, 3, 4], "nestedstringcolumn":"val_2"}], 2:[{"nestedintscolumn":[0, 1, 2], "nestedstringcolumn":"val_0"}, {"nestedintscolumn":[1, 2, 3], "nestedstringcolumn":"val_1"}, {"nestedintscolumn":[2, 3, 4], "nestedstringcolumn":"val_2"}]} true 2 3 4 20 2.2 val_2 val_2 DIAMONDS true 2 3 4 20 2.2 val_2 val_2 DIAMONDS ["arr_2", "arr_3", "arr_4"] [2] {2:"val_2", 3:"val_3", 4:"val_4"} {2:[{"nestedintscolumn":[2, 3, 4], "nestedstringcolumn":"val_2"}, {"nestedintscolumn":[3, 4, 5], "nestedstringcolumn":"val_3"}, {"nestedintscolumn":[4, 5, 6], "nestedstringcolumn":"val_4"}], 3:[{"nestedintscolumn":[2, 3, 4], "nestedstringcolumn":"val_2"}, {"nestedintscolumn":[3, 4, 5], "nestedstringcolumn":"val_3"}, {"nestedintscolumn":[4, 5, 6], "nestedstringcolumn":"val_4"}], 4:[{"nestedintscolumn":[2, 3, 4], "nestedstringcolumn":"val_2"}, {"nestedintscolumn":[3, 4, 5], "nestedstringcolumn":"val_3"}, {"nestedintscolumn":[4, 5, 6], "nestedstringcolumn":"val_4"}]} true 4 5 6 40 4.2 val_4 val_4 SPADES true 4 5 6 40 4.2 val_4 val_4 SPADES ["arr_4", "arr_5", "arr_6"] [4] {4:"val_4", 5:"val_5", 6:"val_6"} {4:[{"nestedintscolumn":[4, 5, 6], "nestedstringcolumn":"val_4"}, {"nestedintscolumn":[5, 6, 7], "nestedstringcolumn":"val_5"}, {"nestedintscolumn":[6, 7, 8], "nestedstringcolumn":"val_6"}], 5:[{"nestedintscolumn":[4, 5, 6], "nestedstringcolumn":"val_4"}, {"nestedintscolumn":[5, 6, 7], "nestedstringcolumn":"val_5"}, {"nestedintscolumn":[6, 7, 8], "nestedstringcolumn":"val_6"}], 6:[{"nestedintscolumn":[4, 5, 6], "nestedstringcolumn":"val_4"}, {"nestedintscolumn":[5, 6, 7], "nestedstringcolumn":"val_5"}, {"nestedintscolumn":[6, 7, 8], "nestedstringcolumn":"val_6"}]} true 6 7 8 60 6.2 val_6 val_6 DIAMONDS \N \N \N \N \N \N \N \N \N ["arr_6", "arr_7", "arr_8"] [6] {6:"val_6", 7:"val_7", 8:"val_8"} {6:[{"nestedintscolumn":[6, 7, 8], "nestedstringcolumn":"val_6"}, {"nestedintscolumn":[7, 8, 9], "nestedstringcolumn":"val_7"}, {"nestedintscolumn":[8, 9, 10], "nestedstringcolumn":"val_8"}], 7:[{"nestedintscolumn":[6, 7, 8], "nestedstringcolumn":"val_6"}, {"nestedintscolumn":[7, 8, 9], "nestedstringcolumn":"val_7"}, {"nestedintscolumn":[8, 9, 10], "nestedstringcolumn":"val_8"}], 8:[{"nestedintscolumn":[6, 7, 8], "nestedstringcolumn":"val_6"}, {"nestedintscolumn":[7, 8, 9], "nestedstringcolumn":"val_7"}, {"nestedintscolumn":[8, 9, 10], "nestedstringcolumn":"val_8"}]} -true 8 9 10 80 8.199999999999999 val_8 val_8 SPADES true 8 9 10 80 8.199999999999999 val_8 val_8 SPADES ["arr_8", "arr_9", "arr_10"] [8] {8:"val_8", 9:"val_9", 10:"val_10"} {8:[{"nestedintscolumn":[8, 9, 10], "nestedstringcolumn":"val_8"}, {"nestedintscolumn":[9, 10, 11], "nestedstringcolumn":"val_9"}, {"nestedintscolumn":[10, 11, 12], "nestedstringcolumn":"val_10"}], 9:[{"nestedintscolumn":[8, 9, 10], "nestedstringcolumn":"val_8"}, {"nestedintscolumn":[9, 10, 11], "nestedstringcolumn":"val_9"}, {"nestedintscolumn":[10, 11, 12], "nestedstringcolumn":"val_10"}], 10:[{"nestedintscolumn":[8, 9, 10], "nestedstringcolumn":"val_8"}, {"nestedintscolumn":[9, 10, 11], "nestedstringcolumn":"val_9"}, {"nestedintscolumn":[10, 11, 12], "nestedstringcolumn":"val_10"}]} +true 8 9 10 80 8.2 val_8 val_8 SPADES true 8 9 10 80 8.2 val_8 val_8 SPADES ["arr_8", "arr_9", "arr_10"] [8] {8:"val_8", 9:"val_9", 10:"val_10"} {8:[{"nestedintscolumn":[8, 9, 10], "nestedstringcolumn":"val_8"}, {"nestedintscolumn":[9, 10, 11], "nestedstringcolumn":"val_9"}, {"nestedintscolumn":[10, 11, 12], "nestedstringcolumn":"val_10"}], 9:[{"nestedintscolumn":[8, 9, 10], "nestedstringcolumn":"val_8"}, {"nestedintscolumn":[9, 10, 11], "nestedstringcolumn":"val_9"}, {"nestedintscolumn":[10, 11, 12], "nestedstringcolumn":"val_10"}], 10:[{"nestedintscolumn":[8, 9, 10], "nestedstringcolumn":"val_8"}, {"nestedintscolumn":[9, 10, 11], "nestedstringcolumn":"val_9"}, {"nestedintscolumn":[10, 11, 12], "nestedstringcolumn":"val_10"}]} -- !test_25 -- {"duration":"111222333444"} diff --git a/regression-test/data/nereids_function_p0/agg_function/agg.out b/regression-test/data/nereids_function_p0/agg_function/agg.out index d0f3dfc22a60d3..655b92dd43280a 100644 --- a/regression-test/data/nereids_function_p0/agg_function/agg.out +++ b/regression-test/data/nereids_function_p0/agg_function/agg.out @@ -6996,3 +6996,201 @@ true 10 [11] 11 [12] +-- !sql_sequence_count_String_TimestampNs_Boolean_gb -- +0 +1 +0 + +-- !sql_sequence_count_String_TimestampNs_Boolean -- +1 + +-- !sql_sequence_count_String_TimestampNs_Boolean_agg_phase_1 -- +0 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 + +-- !sql_sequence_count_String_TimestampNs_Boolean_agg_phase_2 -- +12 1 + +-- !sql_sequence_count_String_TimestampNs_Boolean_agg_phase_3 -- +0 0 +7 1 +5 0 + +-- !sql_sequence_count_String_TimestampNs_Boolean_agg_phase_4 -- +12 1 + +-- !sql_sequence_count_String_TimestampNs_Boolean_gb_notnull -- +1 +0 + +-- !sql_sequence_count_String_TimestampNs_Boolean_notnull -- +1 + +-- !sql_sequence_count_String_TimestampNs_Boolean_agg_phase_1_notnull -- +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 + +-- !sql_sequence_count_String_TimestampNs_Boolean_agg_phase_2_notnull -- +12 1 + +-- !sql_sequence_count_String_TimestampNs_Boolean_agg_phase_3_notnull -- +0 0 +7 1 +5 0 + +-- !sql_sequence_count_String_TimestampNs_Boolean_agg_phase_4_notnull -- +12 1 + +-- !sql_sequence_match_String_TimestampNs_Boolean_gb -- +\N +true +false + +-- !sql_sequence_match_String_TimestampNs_Boolean -- +true + +-- !sql_sequence_match_String_TimestampNs_Boolean_agg_phase_1 -- +0 \N +1 false +1 false +1 false +1 false +1 false +1 false +1 false +1 false +1 false +1 false +1 false +1 false + +-- !sql_sequence_match_String_TimestampNs_Boolean_agg_phase_2 -- +12 true + +-- !sql_sequence_match_String_TimestampNs_Boolean_agg_phase_3 -- +0 \N +7 true +5 false + +-- !sql_sequence_match_String_TimestampNs_Boolean_agg_phase_4 -- +12 true + +-- !sql_sequence_match_String_TimestampNs_Boolean_gb_notnull -- +true +false + +-- !sql_sequence_match_String_TimestampNs_Boolean_notnull -- +true + +-- !sql_sequence_match_String_TimestampNs_Boolean_agg_phase_1_notnull -- +1 false +1 false +1 false +1 false +1 false +1 false +1 false +1 false +1 false +1 false +1 false +1 false + +-- !sql_sequence_match_String_TimestampNs_Boolean_agg_phase_2_notnull -- +12 true + +-- !sql_sequence_match_String_TimestampNs_Boolean_agg_phase_3_notnull -- +0 \N +7 true +5 false + +-- !sql_sequence_match_String_TimestampNs_Boolean_agg_phase_4_notnull -- +12 true + +-- !sql_window_funnel_BigInt_String_TimestampNs_Boolean_gb -- +\N +1 +0 + +-- !sql_window_funnel_BigInt_String_TimestampNs_Boolean -- +1 + +-- !sql_window_funnel_BigInt_String_TimestampNs_Boolean_agg_phase_1 -- +0 \N +1 1 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 + +-- !sql_window_funnel_BigInt_String_TimestampNs_Boolean_agg_phase_2 -- +12 1 + +-- !sql_window_funnel_BigInt_String_TimestampNs_Boolean_agg_phase_3 -- +0 \N +7 1 +5 0 + +-- !sql_window_funnel_BigInt_String_TimestampNs_Boolean_agg_phase_4 -- +12 1 + +-- !sql_window_funnel_BigInt_String_TimestampNs_Boolean_gb_notnull -- +1 +0 + +-- !sql_window_funnel_BigInt_String_TimestampNs_Boolean_notnull -- +1 + +-- !sql_window_funnel_BigInt_String_TimestampNs_Boolean_agg_phase_1_notnull -- +1 1 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 +1 0 + +-- !sql_window_funnel_BigInt_String_TimestampNs_Boolean_agg_phase_2_notnull -- +12 1 + +-- !sql_window_funnel_BigInt_String_TimestampNs_Boolean_agg_phase_3_notnull -- +0 \N +7 1 +5 0 + +-- !sql_window_funnel_BigInt_String_TimestampNs_Boolean_agg_phase_4_notnull -- +12 1 + diff --git a/regression-test/data/nereids_function_p0/gen_function/gen.out b/regression-test/data/nereids_function_p0/gen_function/gen.out index 286a05ee85bff2..ecb649c0e5476c 100644 --- a/regression-test/data/nereids_function_p0/gen_function/gen.out +++ b/regression-test/data/nereids_function_p0/gen_function/gen.out @@ -1496,6 +1496,56 @@ 9 2012-03-10T10:09:10 9 2012-03-10T10:09:10 +-- !sql_explode_TimestampNs -- +0 2012-03-01 01:00:01.000000000 +0 2012-03-01 01:00:01.000000000 +0 2012-03-01 01:00:01.000000000 +0 2012-03-01 01:00:01.000000000 +1 2012-03-02 02:01:02.000000000 +1 2012-03-02 02:01:02.000000000 +1 2012-03-02 02:01:02.000000000 +1 2012-03-02 02:01:02.000000000 +10 2012-03-11 11:10:11.000000000 +10 2012-03-11 11:10:11.000000000 +10 2012-03-11 11:10:11.000000000 +10 2012-03-11 11:10:11.000000000 +11 2012-03-12 12:11:12.000000000 +11 2012-03-12 12:11:12.000000000 +11 2012-03-12 12:11:12.000000000 +11 2012-03-12 12:11:12.000000000 +2 2012-03-03 03:02:03.000000000 +2 2012-03-03 03:02:03.000000000 +2 2012-03-03 03:02:03.000000000 +2 2012-03-03 03:02:03.000000000 +3 2012-03-04 04:03:04.000000000 +3 2012-03-04 04:03:04.000000000 +3 2012-03-04 04:03:04.000000000 +3 2012-03-04 04:03:04.000000000 +4 2012-03-05 05:04:05.000000000 +4 2012-03-05 05:04:05.000000000 +4 2012-03-05 05:04:05.000000000 +4 2012-03-05 05:04:05.000000000 +5 2012-03-06 06:05:06.000000000 +5 2012-03-06 06:05:06.000000000 +5 2012-03-06 06:05:06.000000000 +5 2012-03-06 06:05:06.000000000 +6 2012-03-07 07:06:07.000000000 +6 2012-03-07 07:06:07.000000000 +6 2012-03-07 07:06:07.000000000 +6 2012-03-07 07:06:07.000000000 +7 2012-03-08 08:07:08.000000000 +7 2012-03-08 08:07:08.000000000 +7 2012-03-08 08:07:08.000000000 +7 2012-03-08 08:07:08.000000000 +8 2012-03-09 09:08:09.000000000 +8 2012-03-09 09:08:09.000000000 +8 2012-03-09 09:08:09.000000000 +8 2012-03-09 09:08:09.000000000 +9 2012-03-10 10:09:10.000000000 +9 2012-03-10 10:09:10.000000000 +9 2012-03-10 10:09:10.000000000 +9 2012-03-10 10:09:10.000000000 + -- !sql_explode_DatetimeV2_notnull -- 0 2012-03-01T01:00:01 0 2012-03-01T01:00:01 @@ -1546,6 +1596,56 @@ 9 2012-03-10T10:09:10 9 2012-03-10T10:09:10 +-- !sql_explode_TimestampNs_notnull -- +0 2012-03-01 01:00:01.000000000 +0 2012-03-01 01:00:01.000000000 +0 2012-03-01 01:00:01.000000000 +0 2012-03-01 01:00:01.000000000 +1 2012-03-02 02:01:02.000000000 +1 2012-03-02 02:01:02.000000000 +1 2012-03-02 02:01:02.000000000 +1 2012-03-02 02:01:02.000000000 +10 2012-03-11 11:10:11.000000000 +10 2012-03-11 11:10:11.000000000 +10 2012-03-11 11:10:11.000000000 +10 2012-03-11 11:10:11.000000000 +11 2012-03-12 12:11:12.000000000 +11 2012-03-12 12:11:12.000000000 +11 2012-03-12 12:11:12.000000000 +11 2012-03-12 12:11:12.000000000 +2 2012-03-03 03:02:03.000000000 +2 2012-03-03 03:02:03.000000000 +2 2012-03-03 03:02:03.000000000 +2 2012-03-03 03:02:03.000000000 +3 2012-03-04 04:03:04.000000000 +3 2012-03-04 04:03:04.000000000 +3 2012-03-04 04:03:04.000000000 +3 2012-03-04 04:03:04.000000000 +4 2012-03-05 05:04:05.000000000 +4 2012-03-05 05:04:05.000000000 +4 2012-03-05 05:04:05.000000000 +4 2012-03-05 05:04:05.000000000 +5 2012-03-06 06:05:06.000000000 +5 2012-03-06 06:05:06.000000000 +5 2012-03-06 06:05:06.000000000 +5 2012-03-06 06:05:06.000000000 +6 2012-03-07 07:06:07.000000000 +6 2012-03-07 07:06:07.000000000 +6 2012-03-07 07:06:07.000000000 +6 2012-03-07 07:06:07.000000000 +7 2012-03-08 08:07:08.000000000 +7 2012-03-08 08:07:08.000000000 +7 2012-03-08 08:07:08.000000000 +7 2012-03-08 08:07:08.000000000 +8 2012-03-09 09:08:09.000000000 +8 2012-03-09 09:08:09.000000000 +8 2012-03-09 09:08:09.000000000 +8 2012-03-09 09:08:09.000000000 +9 2012-03-10 10:09:10.000000000 +9 2012-03-10 10:09:10.000000000 +9 2012-03-10 10:09:10.000000000 +9 2012-03-10 10:09:10.000000000 + -- !sql_explode_DateV2 -- 0 2012-03-01 0 2012-03-01 diff --git a/regression-test/data/nereids_function_p0/scalar_function/Array.out b/regression-test/data/nereids_function_p0/scalar_function/Array.out index dd83a01d19f3bb..33c8f92286d561 100644 --- a/regression-test/data/nereids_function_p0/scalar_function/Array.out +++ b/regression-test/data/nereids_function_p0/scalar_function/Array.out @@ -594,6 +594,21 @@ ["2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000"] +-- !sql_array_compact_TimestampNs -- +\N +["2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000"] + -- !sql_array_compact_DatetimeV2_notnull -- ["2012-03-01 01:00:01.000000"] ["2012-03-02 02:01:02.000000"] @@ -608,6 +623,20 @@ ["2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000"] +-- !sql_array_compact_TimestampNs_notnull -- +["2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000"] + -- !sql_array_compact_DateV2 -- \N ["2012-03-01"] @@ -1000,6 +1029,21 @@ ["2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000"] +-- !sql_array_concat_TimestampNs -- +\N +["2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000"] + -- !sql_array_concat_DatetimeV2_notnull -- ["2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000"] ["2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000"] @@ -1014,6 +1058,20 @@ ["2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000"] +-- !sql_array_concat_TimestampNs_notnull -- +["2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000"] + -- !sql_array_concat_DateV2 -- \N ["2012-03-01", "2012-03-01", "2012-03-01", "2012-03-01"] @@ -1754,6 +1812,21 @@ ["2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000"] +-- !sql_array_distinct_TimestampNs -- +\N +["2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000"] + -- !sql_array_distinct_DatetimeV2_notnull -- ["2012-03-01 01:00:01.000000"] ["2012-03-02 02:01:02.000000"] @@ -1768,6 +1841,20 @@ ["2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000"] +-- !sql_array_distinct_TimestampNs_notnull -- +["2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000"] + -- !sql_array_distinct_DateV2 -- \N ["2012-03-01"] @@ -2160,6 +2247,21 @@ [] [] +-- !sql_array_except_TimestampNs -- +\N +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] + -- !sql_array_except_DatetimeV2_notnull -- [] [] @@ -2174,6 +2276,20 @@ [] [] +-- !sql_array_except_TimestampNs_notnull -- +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] + -- !sql_array_except_DateV2 -- \N [] @@ -2566,6 +2682,21 @@ ["2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000"] +-- !sql_array_intersect_TimestampNs -- +\N +["2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000"] + -- !sql_array_intersect_DatetimeV2_notnull -- ["2012-03-01 01:00:01.000000"] ["2012-03-02 02:01:02.000000"] @@ -2580,6 +2711,20 @@ ["2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000"] +-- !sql_array_intersect_TimestampNs_notnull -- +["2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000"] + -- !sql_array_intersect_DateV2 -- \N ["2012-03-01"] @@ -2972,6 +3117,21 @@ char23,char33,varchar13,varchar23,varchar33,string3 2012-03-11 11:10:11.000000,2012-03-11 11:10:11.000000,2012-03-11 11:10:11.000000,2012-03-11 11:10:11.000000 2012-03-12 12:11:12.000000,2012-03-12 12:11:12.000000,2012-03-12 12:11:12.000000,2012-03-12 12:11:12.000000 +-- !sql_array_join_TimestampNs -- +\N +2012-03-01 01:00:01.000000000,2012-03-01 01:00:01.000000000,2012-03-01 01:00:01.000000000,2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000,2012-03-02 02:01:02.000000000,2012-03-02 02:01:02.000000000,2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000,2012-03-03 03:02:03.000000000,2012-03-03 03:02:03.000000000,2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000,2012-03-04 04:03:04.000000000,2012-03-04 04:03:04.000000000,2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000,2012-03-05 05:04:05.000000000,2012-03-05 05:04:05.000000000,2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000,2012-03-06 06:05:06.000000000,2012-03-06 06:05:06.000000000,2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000,2012-03-07 07:06:07.000000000,2012-03-07 07:06:07.000000000,2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000,2012-03-08 08:07:08.000000000,2012-03-08 08:07:08.000000000,2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000,2012-03-09 09:08:09.000000000,2012-03-09 09:08:09.000000000,2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000,2012-03-10 10:09:10.000000000,2012-03-10 10:09:10.000000000,2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000,2012-03-11 11:10:11.000000000,2012-03-11 11:10:11.000000000,2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000,2012-03-12 12:11:12.000000000,2012-03-12 12:11:12.000000000,2012-03-12 12:11:12.000000000 + -- !sql_array_join_DatetimeV2_notnull -- 2012-03-01 01:00:01.000000,2012-03-01 01:00:01.000000,2012-03-01 01:00:01.000000,2012-03-01 01:00:01.000000 2012-03-02 02:01:02.000000,2012-03-02 02:01:02.000000,2012-03-02 02:01:02.000000,2012-03-02 02:01:02.000000 @@ -2986,6 +3146,20 @@ char23,char33,varchar13,varchar23,varchar33,string3 2012-03-11 11:10:11.000000,2012-03-11 11:10:11.000000,2012-03-11 11:10:11.000000,2012-03-11 11:10:11.000000 2012-03-12 12:11:12.000000,2012-03-12 12:11:12.000000,2012-03-12 12:11:12.000000,2012-03-12 12:11:12.000000 +-- !sql_array_join_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000,2012-03-01 01:00:01.000000000,2012-03-01 01:00:01.000000000,2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000,2012-03-02 02:01:02.000000000,2012-03-02 02:01:02.000000000,2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000,2012-03-03 03:02:03.000000000,2012-03-03 03:02:03.000000000,2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000,2012-03-04 04:03:04.000000000,2012-03-04 04:03:04.000000000,2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000,2012-03-05 05:04:05.000000000,2012-03-05 05:04:05.000000000,2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000,2012-03-06 06:05:06.000000000,2012-03-06 06:05:06.000000000,2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000,2012-03-07 07:06:07.000000000,2012-03-07 07:06:07.000000000,2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000,2012-03-08 08:07:08.000000000,2012-03-08 08:07:08.000000000,2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000,2012-03-09 09:08:09.000000000,2012-03-09 09:08:09.000000000,2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000,2012-03-10 10:09:10.000000000,2012-03-10 10:09:10.000000000,2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000,2012-03-11 11:10:11.000000000,2012-03-11 11:10:11.000000000,2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000,2012-03-12 12:11:12.000000000,2012-03-12 12:11:12.000000000,2012-03-12 12:11:12.000000000 + -- !sql_array_join_DateV2 -- \N 2012-03-01,2012-03-01 @@ -3378,6 +3552,21 @@ char23,char33,varchar13,varchar23,varchar33,string3 2012-03-11 11:10:11.000000,2012-03-11 11:10:11.000000,2012-03-11 11:10:11.000000,2012-03-11 11:10:11.000000 2012-03-12 12:11:12.000000,2012-03-12 12:11:12.000000,2012-03-12 12:11:12.000000,2012-03-12 12:11:12.000000 +-- !sql_array_join_two_params_TimestampNs -- +\N +2012-03-01 01:00:01.000000000,2012-03-01 01:00:01.000000000,2012-03-01 01:00:01.000000000,2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000,2012-03-02 02:01:02.000000000,2012-03-02 02:01:02.000000000,2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000,2012-03-03 03:02:03.000000000,2012-03-03 03:02:03.000000000,2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000,2012-03-04 04:03:04.000000000,2012-03-04 04:03:04.000000000,2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000,2012-03-05 05:04:05.000000000,2012-03-05 05:04:05.000000000,2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000,2012-03-06 06:05:06.000000000,2012-03-06 06:05:06.000000000,2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000,2012-03-07 07:06:07.000000000,2012-03-07 07:06:07.000000000,2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000,2012-03-08 08:07:08.000000000,2012-03-08 08:07:08.000000000,2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000,2012-03-09 09:08:09.000000000,2012-03-09 09:08:09.000000000,2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000,2012-03-10 10:09:10.000000000,2012-03-10 10:09:10.000000000,2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000,2012-03-11 11:10:11.000000000,2012-03-11 11:10:11.000000000,2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000,2012-03-12 12:11:12.000000000,2012-03-12 12:11:12.000000000,2012-03-12 12:11:12.000000000 + -- !sql_array_join_two_params_DatetimeV2_notnull -- 2012-03-01 01:00:01.000000,2012-03-01 01:00:01.000000,2012-03-01 01:00:01.000000,2012-03-01 01:00:01.000000 2012-03-02 02:01:02.000000,2012-03-02 02:01:02.000000,2012-03-02 02:01:02.000000,2012-03-02 02:01:02.000000 @@ -3392,6 +3581,20 @@ char23,char33,varchar13,varchar23,varchar33,string3 2012-03-11 11:10:11.000000,2012-03-11 11:10:11.000000,2012-03-11 11:10:11.000000,2012-03-11 11:10:11.000000 2012-03-12 12:11:12.000000,2012-03-12 12:11:12.000000,2012-03-12 12:11:12.000000,2012-03-12 12:11:12.000000 +-- !sql_array_join_two_params_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000,2012-03-01 01:00:01.000000000,2012-03-01 01:00:01.000000000,2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000,2012-03-02 02:01:02.000000000,2012-03-02 02:01:02.000000000,2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000,2012-03-03 03:02:03.000000000,2012-03-03 03:02:03.000000000,2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000,2012-03-04 04:03:04.000000000,2012-03-04 04:03:04.000000000,2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000,2012-03-05 05:04:05.000000000,2012-03-05 05:04:05.000000000,2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000,2012-03-06 06:05:06.000000000,2012-03-06 06:05:06.000000000,2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000,2012-03-07 07:06:07.000000000,2012-03-07 07:06:07.000000000,2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000,2012-03-08 08:07:08.000000000,2012-03-08 08:07:08.000000000,2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000,2012-03-09 09:08:09.000000000,2012-03-09 09:08:09.000000000,2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000,2012-03-10 10:09:10.000000000,2012-03-10 10:09:10.000000000,2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000,2012-03-11 11:10:11.000000000,2012-03-11 11:10:11.000000000,2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000,2012-03-12 12:11:12.000000000,2012-03-12 12:11:12.000000000,2012-03-12 12:11:12.000000000 + -- !sql_array_join_two_params_DateV2 -- \N 2012-03-01,2012-03-01 @@ -3697,6 +3900,21 @@ true 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_array_max_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_array_max_DatetimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -3711,6 +3929,20 @@ true 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_array_max_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_array_max_DateV2 -- \N 2012-03-01 @@ -4016,6 +4248,21 @@ true 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_array_min_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_array_min_DatetimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -4030,6 +4277,20 @@ true 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_array_min_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_array_min_DateV2 -- \N 2012-03-01 @@ -4422,6 +4683,21 @@ true ["2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000"] +-- !sql_array_popback_TimestampNs -- +\N +["2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000"] + -- !sql_array_popback_DatetimeV2_notnull -- ["2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000"] ["2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000"] @@ -4436,6 +4712,20 @@ true ["2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000"] +-- !sql_array_popback_TimestampNs_notnull -- +["2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000"] + -- !sql_array_popback_DateV2 -- \N ["2012-03-01"] @@ -4828,6 +5118,21 @@ true ["2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000"] +-- !sql_array_popfront_TimestampNs -- +\N +["2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000"] + -- !sql_array_popfront_DatetimeV2_notnull -- ["2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000"] ["2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000"] @@ -4842,6 +5147,20 @@ true ["2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000"] +-- !sql_array_popfront_TimestampNs_notnull -- +["2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000"] + -- !sql_array_popfront_DateV2 -- \N ["2012-03-01"] @@ -5234,6 +5553,21 @@ true 1 1 +-- !sql_array_position_TimestampNs -- +\N +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 + -- !sql_array_position_DatetimeV2_notnull -- 1 1 @@ -5248,6 +5582,20 @@ true 1 1 +-- !sql_array_position_TimestampNs_notnull -- +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 + -- !sql_array_position_DateV2 -- \N 1 @@ -5872,6 +6220,21 @@ true ["2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000"] +-- !sql_array_pushback_TimestampNs -- +\N +["2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000"] + -- !sql_array_pushback_DatetimeV2_notnull -- ["2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000"] ["2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000"] @@ -5886,6 +6249,20 @@ true ["2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000"] +-- !sql_array_pushback_TimestampNs_notnull -- +["2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000"] + -- !sql_array_pushback_DateV2 -- \N ["2012-03-01", "2012-03-01", "2012-03-01"] @@ -6278,6 +6655,21 @@ true ["2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000"] +-- !sql_array_pushfront_TimestampNs -- +\N +["2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000"] + -- !sql_array_pushfront_DatetimeV2_notnull -- ["2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000"] ["2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000"] @@ -6292,6 +6684,20 @@ true ["2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000"] +-- !sql_array_pushfront_TimestampNs_notnull -- +["2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000"] + -- !sql_array_pushfront_DateV2 -- \N ["2012-03-01", "2012-03-01", "2012-03-01"] @@ -6771,6 +7177,21 @@ true [] [] +-- !sql_array_remove_TimestampNs -- +\N +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] + -- !sql_array_remove_DatetimeV2_notnull -- [] [] @@ -6785,6 +7206,20 @@ true [] [] +-- !sql_array_remove_TimestampNs_notnull -- +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] + -- !sql_array_remove_DateV2 -- \N [] @@ -7177,6 +7612,21 @@ true ["2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000"] +-- !sql_array_reverse_sort_TimestampNs -- +\N +["2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000"] + -- !sql_array_reverse_sort_DatetimeV2_notnull -- ["2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000"] ["2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000"] @@ -7191,6 +7641,20 @@ true ["2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000"] +-- !sql_array_reverse_sort_TimestampNs_notnull -- +["2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000"] + -- !sql_array_reverse_sort_DateV2 -- \N ["2012-03-01", "2012-03-01"] @@ -7583,6 +8047,21 @@ true [] [] +-- !sql_array_slice_TimestampNs -- +\N +["2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] + -- !sql_array_slice_DatetimeV2_notnull -- ["2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000"] ["2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000"] @@ -7597,6 +8076,20 @@ true [] [] +-- !sql_array_slice_TimestampNs_notnull -- +["2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] + -- !sql_array_slice_DateV2 -- \N ["2012-03-01", "2012-03-01"] @@ -7989,6 +8482,21 @@ true [] [] +-- !sql_array_slice_three_params_TimestampNs -- +\N +["2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] + -- !sql_array_slice_three_params_DatetimeV2_notnull -- ["2012-03-01 01:00:01.000000"] ["2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000"] @@ -8003,6 +8511,20 @@ true [] [] +-- !sql_array_slice_three_params_TimestampNs_notnull -- +["2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] + -- !sql_array_slice_three_params_DateV2 -- \N ["2012-03-01"] @@ -8395,6 +8917,21 @@ true ["2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000"] +-- !sql_array_sort_TimestampNs -- +\N +["2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000"] + -- !sql_array_sort_DatetimeV2_notnull -- ["2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000", "2012-03-01 01:00:01.000000"] ["2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000", "2012-03-02 02:01:02.000000"] @@ -8409,6 +8946,20 @@ true ["2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000", "2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000", "2012-03-12 12:11:12.000000"] +-- !sql_array_sort_TimestampNs_notnull -- +["2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000", "2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000"] + -- !sql_array_sort_DateV2 -- \N ["2012-03-01", "2012-03-01"] @@ -9033,6 +9584,21 @@ true ["2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000"] +-- !sql_array_union_TimestampNs -- +\N +["2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000"] + -- !sql_array_union_DatetimeV2_notnull -- ["2012-03-01 01:00:01.000000"] ["2012-03-02 02:01:02.000000"] @@ -9047,6 +9613,20 @@ true ["2012-03-11 11:10:11.000000"] ["2012-03-12 12:11:12.000000"] +-- !sql_array_union_TimestampNs_notnull -- +["2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000"] + -- !sql_array_union_DateV2 -- \N ["2012-03-01"] @@ -9439,6 +10019,21 @@ true ["2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12"] [] +-- !sql_array_with_constant_TimestampNs -- +["2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000"] +[] + -- !sql_array_with_constant_DatetimeV2_notnull -- ["2012-03-01 01:00:01"] ["2012-03-02 02:01:02", "2012-03-02 02:01:02"] @@ -9453,6 +10048,20 @@ true ["2012-03-11 11:10:11", "2012-03-11 11:10:11", "2012-03-11 11:10:11", "2012-03-11 11:10:11", "2012-03-11 11:10:11", "2012-03-11 11:10:11", "2012-03-11 11:10:11", "2012-03-11 11:10:11", "2012-03-11 11:10:11", "2012-03-11 11:10:11", "2012-03-11 11:10:11"] ["2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12", "2012-03-12 12:11:12"] +-- !sql_array_with_constant_TimestampNs_notnull -- +["2012-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000", "2012-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000", "2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000", "2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000", "2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000", "2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000", "2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000", "2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000", "2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000", "2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000", "2012-03-12 12:11:12.000000000"] + -- !sql_array_with_constant_DateV2 -- ["2012-03-01"] ["2012-03-02", "2012-03-02"] @@ -9845,6 +10454,21 @@ true 4 4 +-- !sql_cardinality_TimestampNs -- +\N +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 + -- !sql_cardinality_DatetimeV2_notnull -- 4 4 @@ -9859,6 +10483,20 @@ true 4 4 +-- !sql_cardinality_TimestampNs_notnull -- +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 + -- !sql_cardinality_DateV2 -- \N 2 @@ -10251,6 +10889,21 @@ true 4 4 +-- !sql_array_size_TimestampNs -- +\N +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 + -- !sql_array_size_DatetimeV2_notnull -- 4 4 @@ -10265,6 +10918,20 @@ true 4 4 +-- !sql_array_size_TimestampNs_notnull -- +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 + -- !sql_array_size_DateV2 -- \N 2 @@ -10657,6 +11324,21 @@ true 4 4 +-- !sql_size_TimestampNs -- +\N +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 + -- !sql_size_DatetimeV2_notnull -- 4 4 @@ -10671,6 +11353,20 @@ true 4 4 +-- !sql_size_TimestampNs_notnull -- +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 + -- !sql_size_DateV2 -- \N 2 @@ -13356,6 +14052,18 @@ true \N \N +-- !array_apply_timestamp_ns_eq -- +[] +[] + +-- !array_apply_timestamp_ns_gt -- +["2022-12-01 22:23:25.000000000", "2022-12-01 23:23:25.000000000"] +["2022-12-02 22:23:25.000000000", "2022-12-02 23:23:25.000000000"] + +-- !array_apply_timestamp_ns_null -- +\N +\N + -- !array_apply4 -- [22.679] [] @@ -13395,6 +14103,21 @@ true ["2012-03-11 11:10:11", "2012-03-22 11:10:11"] ["2012-03-12 12:11:12", "2012-03-24 12:11:12"] +-- !array_range_datetime1_timestamp_ns -- +\N +["2012-03-01 01:00:01.000000000", "2012-03-02 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-04 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-06 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-08 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-10 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-12 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-14 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-16 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-18 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-20 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-22 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-24 12:11:12.000000000"] + -- !array_range_datetime2 -- \N ["2012-03-01 01:00:01", "2012-03-08 01:00:01", "2012-03-15 01:00:01"] @@ -13410,6 +14133,21 @@ true ["2012-03-11 11:10:11", "2012-05-27 11:10:11"] ["2012-03-12 12:11:12", "2012-06-04 12:11:12"] +-- !array_range_datetime2_timestamp_ns -- +\N +["2012-03-01 01:00:01.000000000", "2012-03-08 01:00:01.000000000", "2012-03-15 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-16 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-24 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-04-01 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-04-09 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-04-17 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-04-25 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-05-03 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-05-11 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-05-19 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-05-27 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-06-04 12:11:12.000000000"] + -- !array_range_datetime3 -- \N ["2012-03-01 01:00:01", "2012-06-01 01:00:01", "2012-09-01 01:00:01"] @@ -13425,6 +14163,21 @@ true ["2012-03-11 11:10:11", "2014-12-11 11:10:11"] ["2012-03-12 12:11:12", "2015-03-12 12:11:12"] +-- !array_range_datetime3_timestamp_ns -- +\N +["2012-03-01 01:00:01.000000000", "2012-06-01 01:00:01.000000000", "2012-09-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-09-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-12-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2013-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2013-06-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2013-09-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2013-12-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2014-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2014-06-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2014-09-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2014-12-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2015-03-12 12:11:12.000000000"] + -- !sequence_int_one_para -- \N [0] @@ -13485,6 +14238,21 @@ true ["2012-03-11 11:10:11", "2012-03-12 11:10:11", "2012-03-13 11:10:11", "2012-03-14 11:10:11", "2012-03-15 11:10:11", "2012-03-16 11:10:11", "2012-03-17 11:10:11", "2012-03-18 11:10:11"] ["2012-03-12 12:11:12", "2012-03-13 12:11:12", "2012-03-14 12:11:12", "2012-03-15 12:11:12", "2012-03-16 12:11:12", "2012-03-17 12:11:12", "2012-03-18 12:11:12", "2012-03-19 12:11:12", "2012-03-20 12:11:12"] +-- !sequence_datetime_default_timestamp_ns -- +\N +[] +[] +[] +["2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-06 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-07 06:05:06.000000000", "2012-03-08 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-08 07:06:07.000000000", "2012-03-09 07:06:07.000000000", "2012-03-10 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-09 08:07:08.000000000", "2012-03-10 08:07:08.000000000", "2012-03-11 08:07:08.000000000", "2012-03-12 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-10 09:08:09.000000000", "2012-03-11 09:08:09.000000000", "2012-03-12 09:08:09.000000000", "2012-03-13 09:08:09.000000000", "2012-03-14 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-11 10:09:10.000000000", "2012-03-12 10:09:10.000000000", "2012-03-13 10:09:10.000000000", "2012-03-14 10:09:10.000000000", "2012-03-15 10:09:10.000000000", "2012-03-16 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-12 11:10:11.000000000", "2012-03-13 11:10:11.000000000", "2012-03-14 11:10:11.000000000", "2012-03-15 11:10:11.000000000", "2012-03-16 11:10:11.000000000", "2012-03-17 11:10:11.000000000", "2012-03-18 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-13 12:11:12.000000000", "2012-03-14 12:11:12.000000000", "2012-03-15 12:11:12.000000000", "2012-03-16 12:11:12.000000000", "2012-03-17 12:11:12.000000000", "2012-03-18 12:11:12.000000000", "2012-03-19 12:11:12.000000000", "2012-03-20 12:11:12.000000000"] + -- !sequence_datetime_day -- \N ["2012-03-01 01:00:01", "2012-03-02 01:00:01"] @@ -13500,6 +14268,21 @@ true ["2012-03-11 11:10:11", "2012-03-22 11:10:11"] ["2012-03-12 12:11:12", "2012-03-24 12:11:12"] +-- !sequence_datetime_day_timestamp_ns -- +\N +["2012-03-01 01:00:01.000000000", "2012-03-02 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-04 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-06 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-08 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-10 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-12 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-14 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-16 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-18 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-20 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-22 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-24 12:11:12.000000000"] + -- !sequence_datetime_week -- \N ["2012-03-01 01:00:01", "2012-03-08 01:00:01", "2012-03-15 01:00:01"] @@ -13515,6 +14298,21 @@ true ["2012-03-11 11:10:11", "2012-05-27 11:10:11"] ["2012-03-12 12:11:12", "2012-06-04 12:11:12"] +-- !sequence_datetime_week_timestamp_ns -- +\N +["2012-03-01 01:00:01.000000000", "2012-03-08 01:00:01.000000000", "2012-03-15 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-16 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-24 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-04-01 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-04-09 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-04-17 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-04-25 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-05-03 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-05-11 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-05-19 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-05-27 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-06-04 12:11:12.000000000"] + -- !sequence_datetime_month -- \N ["2012-03-01 01:00:01", "2012-04-01 01:00:01", "2012-05-01 01:00:01", "2012-06-01 01:00:01"] @@ -13530,6 +14328,21 @@ true ["2012-03-11 11:10:11", "2013-02-11 11:10:11"] ["2012-03-12 12:11:12", "2013-03-12 12:11:12"] +-- !sequence_datetime_month_timestamp_ns -- +\N +["2012-03-01 01:00:01.000000000", "2012-04-01 01:00:01.000000000", "2012-05-01 01:00:01.000000000", "2012-06-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-05-02 02:01:02.000000000", "2012-07-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-06-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-07-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-08-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-09-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-10-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-11-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-12-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2013-01-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2013-02-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2013-03-12 12:11:12.000000000"] + -- !sequence_datetime_year -- \N ["2012-03-01 01:00:01", "2013-03-01 01:00:01", "2014-03-01 01:00:01", "2015-03-01 01:00:01"] @@ -13545,6 +14358,21 @@ true ["2012-03-11 11:10:11", "2023-03-11 11:10:11"] ["2012-03-12 12:11:12", "2024-03-12 12:11:12"] +-- !sequence_datetime_year_timestamp_ns -- +\N +["2012-03-01 01:00:01.000000000", "2013-03-01 01:00:01.000000000", "2014-03-01 01:00:01.000000000", "2015-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2014-03-02 02:01:02.000000000", "2016-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2015-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2016-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2017-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2018-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2019-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2020-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2021-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2022-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2023-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2024-03-12 12:11:12.000000000"] + -- !sequence_datetime_hour -- \N [] @@ -13560,6 +14388,21 @@ true ["2012-03-11 11:10:11"] ["2012-03-12 12:11:12"] +-- !sequence_datetime_hour_timestamp_ns -- +\N +[] +[] +[] +["2012-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000"] + -- !sequence_datetime_minute -- \N ["2012-03-01 01:00:01", "2012-03-01 01:01:01"] @@ -13575,6 +14418,21 @@ true ["2012-03-11 11:10:11", "2012-03-11 11:21:11"] ["2012-03-12 12:11:12", "2012-03-12 12:23:12"] +-- !sequence_datetime_minute_timestamp_ns -- +\N +["2012-03-01 01:00:01.000000000", "2012-03-01 01:01:01.000000000"] +["2012-03-02 02:01:02.000000000", "2012-03-02 02:03:02.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:05:03.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-04 04:07:04.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-05 05:09:05.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-06 06:11:06.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-07 07:13:07.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-08 08:15:08.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-09 09:17:09.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-10 10:19:10.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-11 11:21:11.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-12 12:23:12.000000000"] + -- !sequence_datetime_second -- \N \N @@ -13590,6 +14448,21 @@ true ["2012-03-11 11:10:11", "2012-03-11 11:10:21"] ["2012-03-12 12:11:12", "2012-03-12 12:11:23"] +-- !sequence_datetime_second_timestamp_ns -- +\N +\N +["2012-03-02 02:01:02.000000000", "2012-03-02 02:01:03.000000000"] +["2012-03-03 03:02:03.000000000", "2012-03-03 03:02:05.000000000"] +["2012-03-04 04:03:04.000000000", "2012-03-04 04:03:07.000000000"] +["2012-03-05 05:04:05.000000000", "2012-03-05 05:04:09.000000000"] +["2012-03-06 06:05:06.000000000", "2012-03-06 06:05:11.000000000"] +["2012-03-07 07:06:07.000000000", "2012-03-07 07:06:13.000000000"] +["2012-03-08 08:07:08.000000000", "2012-03-08 08:07:15.000000000"] +["2012-03-09 09:08:09.000000000", "2012-03-09 09:08:17.000000000"] +["2012-03-10 10:09:10.000000000", "2012-03-10 10:09:19.000000000"] +["2012-03-11 11:10:11.000000000", "2012-03-11 11:10:21.000000000"] +["2012-03-12 12:11:12.000000000", "2012-03-12 12:11:23.000000000"] + -- !sql_sequence_dt_3args -- \N ["2012-03-01 01:00:01", "2137-03-01 01:00:01", "2262-03-01 01:00:01", "2387-03-01 01:00:01", "2512-03-01 01:00:01", "2637-03-01 01:00:01", "2762-03-01 01:00:01", "2887-03-01 01:00:01", "3012-03-01 01:00:01"] @@ -13605,6 +14478,21 @@ true ["2012-03-11 11:10:11", "2137-03-11 11:10:11", "2262-03-11 11:10:11", "2387-03-11 11:10:11", "2512-03-11 11:10:11", "2637-03-11 11:10:11", "2762-03-11 11:10:11", "2887-03-11 11:10:11", "3012-03-11 11:10:11"] ["2012-03-12 12:11:12", "2137-03-12 12:11:12", "2262-03-12 12:11:12", "2387-03-12 12:11:12", "2512-03-12 12:11:12", "2637-03-12 12:11:12", "2762-03-12 12:11:12", "2887-03-12 12:11:12", "3012-03-12 12:11:12"] +-- !sql_sequence_dt_3args_timestamp_ns -- +\N +["2012-03-01 01:00:01.000000000", "2024-03-01 01:00:01.000000000", "2036-03-01 01:00:01.000000000", "2048-03-01 01:00:01.000000000", "2060-03-01 01:00:01.000000000", "2072-03-01 01:00:01.000000000", "2084-03-01 01:00:01.000000000", "2096-03-01 01:00:01.000000000", "2108-03-01 01:00:01.000000000"] +["2012-03-02 02:01:02.000000000", "2024-03-02 02:01:02.000000000", "2036-03-02 02:01:02.000000000", "2048-03-02 02:01:02.000000000", "2060-03-02 02:01:02.000000000", "2072-03-02 02:01:02.000000000", "2084-03-02 02:01:02.000000000", "2096-03-02 02:01:02.000000000", "2108-03-02 02:01:02.000000000"] +["2012-03-03 03:02:03.000000000", "2024-03-03 03:02:03.000000000", "2036-03-03 03:02:03.000000000", "2048-03-03 03:02:03.000000000", "2060-03-03 03:02:03.000000000", "2072-03-03 03:02:03.000000000", "2084-03-03 03:02:03.000000000", "2096-03-03 03:02:03.000000000", "2108-03-03 03:02:03.000000000"] +["2012-03-04 04:03:04.000000000", "2024-03-04 04:03:04.000000000", "2036-03-04 04:03:04.000000000", "2048-03-04 04:03:04.000000000", "2060-03-04 04:03:04.000000000", "2072-03-04 04:03:04.000000000", "2084-03-04 04:03:04.000000000", "2096-03-04 04:03:04.000000000", "2108-03-04 04:03:04.000000000"] +["2012-03-05 05:04:05.000000000", "2024-03-05 05:04:05.000000000", "2036-03-05 05:04:05.000000000", "2048-03-05 05:04:05.000000000", "2060-03-05 05:04:05.000000000", "2072-03-05 05:04:05.000000000", "2084-03-05 05:04:05.000000000", "2096-03-05 05:04:05.000000000", "2108-03-05 05:04:05.000000000"] +["2012-03-06 06:05:06.000000000", "2024-03-06 06:05:06.000000000", "2036-03-06 06:05:06.000000000", "2048-03-06 06:05:06.000000000", "2060-03-06 06:05:06.000000000", "2072-03-06 06:05:06.000000000", "2084-03-06 06:05:06.000000000", "2096-03-06 06:05:06.000000000", "2108-03-06 06:05:06.000000000"] +["2012-03-07 07:06:07.000000000", "2024-03-07 07:06:07.000000000", "2036-03-07 07:06:07.000000000", "2048-03-07 07:06:07.000000000", "2060-03-07 07:06:07.000000000", "2072-03-07 07:06:07.000000000", "2084-03-07 07:06:07.000000000", "2096-03-07 07:06:07.000000000", "2108-03-07 07:06:07.000000000"] +["2012-03-08 08:07:08.000000000", "2024-03-08 08:07:08.000000000", "2036-03-08 08:07:08.000000000", "2048-03-08 08:07:08.000000000", "2060-03-08 08:07:08.000000000", "2072-03-08 08:07:08.000000000", "2084-03-08 08:07:08.000000000", "2096-03-08 08:07:08.000000000", "2108-03-08 08:07:08.000000000"] +["2012-03-09 09:08:09.000000000", "2024-03-09 09:08:09.000000000", "2036-03-09 09:08:09.000000000", "2048-03-09 09:08:09.000000000", "2060-03-09 09:08:09.000000000", "2072-03-09 09:08:09.000000000", "2084-03-09 09:08:09.000000000", "2096-03-09 09:08:09.000000000", "2108-03-09 09:08:09.000000000", "2120-03-09 09:08:09.000000000"] +["2012-03-10 10:09:10.000000000", "2024-03-10 10:09:10.000000000", "2036-03-10 10:09:10.000000000", "2048-03-10 10:09:10.000000000", "2060-03-10 10:09:10.000000000", "2072-03-10 10:09:10.000000000", "2084-03-10 10:09:10.000000000", "2096-03-10 10:09:10.000000000", "2108-03-10 10:09:10.000000000", "2120-03-10 10:09:10.000000000"] +["2012-03-11 11:10:11.000000000", "2024-03-11 11:10:11.000000000", "2036-03-11 11:10:11.000000000", "2048-03-11 11:10:11.000000000", "2060-03-11 11:10:11.000000000", "2072-03-11 11:10:11.000000000", "2084-03-11 11:10:11.000000000", "2096-03-11 11:10:11.000000000", "2108-03-11 11:10:11.000000000", "2120-03-11 11:10:11.000000000"] +["2012-03-12 12:11:12.000000000", "2024-03-12 12:11:12.000000000", "2036-03-12 12:11:12.000000000", "2048-03-12 12:11:12.000000000", "2060-03-12 12:11:12.000000000", "2072-03-12 12:11:12.000000000", "2084-03-12 12:11:12.000000000", "2096-03-12 12:11:12.000000000", "2108-03-12 12:11:12.000000000", "2120-03-12 12:11:12.000000000"] + -- !sql_sequence_int_3args -- \N [1, 10001, 20001, 30001, 40001, 50001, 60001, 70001, 80001, 90001] diff --git a/regression-test/data/nereids_function_p0/scalar_function/Array1.out b/regression-test/data/nereids_function_p0/scalar_function/Array1.out index 2efd01b377cb3a..504b5eac234d3c 100644 --- a/regression-test/data/nereids_function_p0/scalar_function/Array1.out +++ b/regression-test/data/nereids_function_p0/scalar_function/Array1.out @@ -1065,6 +1065,32 @@ [null] [null] +-- !sql_array_compact_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000"] +[] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_compact_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000"] ["0000-12-13 00:00:00.000000"] @@ -1091,6 +1117,32 @@ [null] [null] +-- !sql_array_compact_TimestampNs_notnull -- +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_compact_DateV2 -- \N \N @@ -1793,6 +1845,32 @@ [null, null] [null, null] +-- !sql_array_concat_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2020-02-29 00:00:00.000000000", "2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, "2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null, "2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null] +["2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null, "2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] +[] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] + -- !sql_array_concat_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000", "0000-01-01 00:00:00.000000"] ["0000-12-13 00:00:00.000000", "0000-12-13 00:00:00.000000"] @@ -1819,6 +1897,32 @@ [null, null] [null, null] +-- !sql_array_concat_TimestampNs_notnull -- +["2020-02-29 00:00:00.000000000", "2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, "2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null, "2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null] +["2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null, "2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] + -- !sql_array_concat_DateV2 -- \N \N @@ -3145,6 +3249,32 @@ [null] [null] +-- !sql_array_distinct_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000"] +[] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_distinct_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000"] ["0000-12-13 00:00:00.000000"] @@ -3171,6 +3301,32 @@ [null] [null] +-- !sql_array_distinct_TimestampNs_notnull -- +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_distinct_DateV2 -- \N \N @@ -3977,6 +4133,32 @@ [] [] +-- !sql_array_except_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] + -- !sql_array_except_DatetimeV2_notnull -- [] [] @@ -4003,6 +4185,32 @@ [] [] +-- !sql_array_except_TimestampNs_notnull -- +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] + -- !sql_array_except_DateV2 -- \N \N @@ -4705,6 +4913,32 @@ [null] [null] +-- !sql_array_intersect_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000"] +[] +[null, "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_intersect_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000", "0000-12-13 00:00:00.000000", "2020-02-29 00:00:00.000000", "2021-02-28 00:00:00.000000", "2021-12-31 00:00:00.000000", "9999-12-31 00:00:00.000000"] ["0000-01-01 00:00:00.000000"] @@ -4731,6 +4965,32 @@ [null] [null] +-- !sql_array_intersect_TimestampNs_notnull -- +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null, "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_intersect_DateV2 -- \N \N @@ -5433,6 +5693,32 @@ null null null +-- !sql_array_join_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N + +2020-02-29 00:00:00.000000000 +2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000,null,null,2020-02-29 00:00:00.000000000,2021-02-28 00:00:00.000000000,null +2021-12-31 00:00:00.000000000,null,null,2020-02-29 00:00:00.000000000,2021-02-28 00:00:00.000000000,null,null,null,null,null,null +2021-12-31 00:00:00.000000000,null,null,null,null,null,null,null,null,null,2020-02-28 00:00:00.000000000,2020-02-29 00:00:00.000000000,2020-03-01 00:00:00.000000000,2021-02-28 00:00:00.000000000,2021-03-01 00:00:00.000000000,1900-02-28 00:00:00.000000000,1900-03-01 00:00:00.000000000,null,1969-12-31 00:00:00.000000000,1970-01-01 00:00:00.000000000,null +null +null +null +null +null +null +null +null +null + -- !sql_array_join_DatetimeV2_notnull -- @@ -5459,6 +5745,32 @@ null null null +-- !sql_array_join_TimestampNs_notnull -- + + + + + + + + + +2020-02-29 00:00:00.000000000 +2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000,null,null,2020-02-29 00:00:00.000000000,2021-02-28 00:00:00.000000000,null +2021-12-31 00:00:00.000000000,null,null,2020-02-29 00:00:00.000000000,2021-02-28 00:00:00.000000000,null,null,null,null,null,null +2021-12-31 00:00:00.000000000,null,null,null,null,null,null,null,null,null,2020-02-28 00:00:00.000000000,2020-02-29 00:00:00.000000000,2020-03-01 00:00:00.000000000,2021-02-28 00:00:00.000000000,2021-03-01 00:00:00.000000000,1900-02-28 00:00:00.000000000,1900-03-01 00:00:00.000000000,null,1969-12-31 00:00:00.000000000,1970-01-01 00:00:00.000000000,null +null +null +null +null +null +null +null +null +null + -- !sql_array_join_DateV2 -- \N \N @@ -6161,6 +6473,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 2021-12-31 00:00:00.000000,0000-01-01 00:00:00.000000,9999-12-31 00:00:00.000000,2020-02-29 00:00:00.000000,2021-02-28 00:00:00.000000,0000-12-13 00:00:00.000000 9999-12-31 00:00:00.000000 +-- !sql_array_join_two_params_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N + + + + + + + + + + +2020-02-29 00:00:00.000000000 +2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000,2020-02-28 00:00:00.000000000,2020-02-29 00:00:00.000000000,2020-03-01 00:00:00.000000000,2021-02-28 00:00:00.000000000,2021-03-01 00:00:00.000000000,1900-02-28 00:00:00.000000000,1900-03-01 00:00:00.000000000,1969-12-31 00:00:00.000000000,1970-01-01 00:00:00.000000000 +2021-12-31 00:00:00.000000000,2020-02-29 00:00:00.000000000,2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000,2020-02-29 00:00:00.000000000,2021-02-28 00:00:00.000000000 + -- !sql_array_join_two_params_DatetimeV2_notnull -- @@ -6187,6 +6525,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 2021-12-31 00:00:00.000000,0000-01-01 00:00:00.000000,9999-12-31 00:00:00.000000,2020-02-29 00:00:00.000000,2021-02-28 00:00:00.000000,0000-12-13 00:00:00.000000 9999-12-31 00:00:00.000000 +-- !sql_array_join_two_params_TimestampNs_notnull -- + + + + + + + + + + + + + + + + + + +2020-02-29 00:00:00.000000000 +2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000,2020-02-28 00:00:00.000000000,2020-02-29 00:00:00.000000000,2020-03-01 00:00:00.000000000,2021-02-28 00:00:00.000000000,2021-03-01 00:00:00.000000000,1900-02-28 00:00:00.000000000,1900-03-01 00:00:00.000000000,1969-12-31 00:00:00.000000000,1970-01-01 00:00:00.000000000 +2021-12-31 00:00:00.000000000,2020-02-29 00:00:00.000000000,2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000,2020-02-29 00:00:00.000000000,2021-02-28 00:00:00.000000000 + -- !sql_array_join_two_params_DateV2 -- \N \N @@ -6733,6 +7097,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 9999-12-31T00:00 9999-12-31T00:00 +-- !sql_array_max_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +2020-02-29 00:00:00.000000000 +2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000 + -- !sql_array_max_DatetimeV2_notnull -- \N \N @@ -6759,6 +7149,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 9999-12-31T00:00 9999-12-31T00:00 +-- !sql_array_max_TimestampNs_notnull -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +2020-02-29 00:00:00.000000000 +2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000 + -- !sql_array_max_DateV2 -- \N \N @@ -7305,6 +7721,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 2021-12-31T00:00 9999-12-31T00:00 +-- !sql_array_min_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +1900-02-28 00:00:00.000000000 +2020-02-29 00:00:00.000000000 +2020-02-29 00:00:00.000000000 +2020-02-29 00:00:00.000000000 +2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000 + -- !sql_array_min_DatetimeV2_notnull -- \N \N @@ -7331,6 +7773,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 2021-12-31T00:00 9999-12-31T00:00 +-- !sql_array_min_TimestampNs_notnull -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +1900-02-28 00:00:00.000000000 +2020-02-29 00:00:00.000000000 +2020-02-29 00:00:00.000000000 +2020-02-29 00:00:00.000000000 +2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000 + -- !sql_array_min_DateV2 -- \N \N @@ -8033,6 +8501,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 [] [] +-- !sql_array_popback_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] + -- !sql_array_popback_DatetimeV2_notnull -- ["2021-12-31 00:00:00.000000", "0000-01-01 00:00:00.000000", "0000-01-02 00:00:00.000000", "0000-01-03 00:00:00.000000", "0000-01-04 00:00:00.000000", "0000-01-05 00:00:00.000000", "0000-01-06 00:00:00.000000", "0000-01-07 00:00:00.000000", "0000-12-31 00:00:00.000000", "0000-02-28 00:00:00.000000", "2020-02-28 00:00:00.000000", "2020-02-29 00:00:00.000000", "2020-03-01 00:00:00.000000", "2021-02-28 00:00:00.000000", "2021-03-01 00:00:00.000000", "1900-02-28 00:00:00.000000", "1900-03-01 00:00:00.000000", "9999-12-31 00:00:00.000000", "1969-12-31 00:00:00.000000", "1970-01-01 00:00:00.000000"] ["2021-12-31 00:00:00.000000", "0000-01-01 00:00:00.000000", "9999-12-31 00:00:00.000000", "2020-02-29 00:00:00.000000", "2021-02-28 00:00:00.000000", null, null, null, "0000-12-13 00:00:00.000000", null] @@ -8059,6 +8553,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 [] [] +-- !sql_array_popback_TimestampNs_notnull -- +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] + -- !sql_array_popback_DateV2 -- \N \N @@ -8761,6 +9281,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 [] [] +-- !sql_array_popfront_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null] +[null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +[null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] + -- !sql_array_popfront_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000", "0000-01-02 00:00:00.000000", "0000-01-03 00:00:00.000000", "0000-01-04 00:00:00.000000", "0000-01-05 00:00:00.000000", "0000-01-06 00:00:00.000000", "0000-01-07 00:00:00.000000", "0000-12-31 00:00:00.000000", "0000-02-28 00:00:00.000000", "2020-02-28 00:00:00.000000", "2020-02-29 00:00:00.000000", "2020-03-01 00:00:00.000000", "2021-02-28 00:00:00.000000", "2021-03-01 00:00:00.000000", "1900-02-28 00:00:00.000000", "1900-03-01 00:00:00.000000", "9999-12-31 00:00:00.000000", "1969-12-31 00:00:00.000000", "1970-01-01 00:00:00.000000", null] ["0000-01-01 00:00:00.000000", "9999-12-31 00:00:00.000000", "2020-02-29 00:00:00.000000", "2021-02-28 00:00:00.000000", "0000-12-13 00:00:00.000000"] @@ -8787,6 +9333,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 [] [] +-- !sql_array_popfront_TimestampNs_notnull -- +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null] +[null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +[null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] + -- !sql_array_popfront_DateV2 -- \N \N @@ -9437,6 +10009,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 1 1 +-- !sql_array_position_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 + -- !sql_array_position_DatetimeV2_notnull -- 0 0 @@ -9463,6 +10061,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 1 1 +-- !sql_array_position_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 + -- !sql_array_position_DateV2 -- \N \N @@ -10373,6 +10997,32 @@ NaN [null, null] [null] +-- !sql_array_pushback_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2020-02-29 00:00:00.000000000", "2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, "2021-12-31 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null, "2021-12-31 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null, "2021-12-31 00:00:00.000000000"] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null] + -- !sql_array_pushback_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000", "0000-01-01 00:00:00.000000"] ["0000-12-13 00:00:00.000000", "0000-12-13 00:00:00.000000"] @@ -10399,6 +11049,32 @@ NaN [null] [null] +-- !sql_array_pushback_TimestampNs_notnull -- +["2020-02-29 00:00:00.000000000", "2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, "2021-12-31 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null, "2021-12-31 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null, "2021-12-31 00:00:00.000000000"] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_pushback_DateV2 -- \N \N @@ -11101,6 +11777,32 @@ NaN [null, null] [null] +-- !sql_array_pushfront_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2020-02-29 00:00:00.000000000", "2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null] + -- !sql_array_pushfront_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000", "0000-01-01 00:00:00.000000"] ["0000-12-13 00:00:00.000000", "0000-12-13 00:00:00.000000"] @@ -11127,6 +11829,32 @@ NaN [null] [null] +-- !sql_array_pushfront_TimestampNs_notnull -- +["2020-02-29 00:00:00.000000000", "2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_pushfront_DateV2 -- \N \N @@ -11829,6 +12557,32 @@ NaN [] [] +-- !sql_array_remove_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null] +[null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +[null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] + -- !sql_array_remove_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000", "0000-01-02 00:00:00.000000", "0000-01-03 00:00:00.000000", "0000-01-04 00:00:00.000000", "0000-01-05 00:00:00.000000", "0000-01-06 00:00:00.000000", "0000-01-07 00:00:00.000000", "0000-12-31 00:00:00.000000", "0000-02-28 00:00:00.000000", "2020-02-28 00:00:00.000000", "2020-02-29 00:00:00.000000", "2020-03-01 00:00:00.000000", "2021-02-28 00:00:00.000000", "2021-03-01 00:00:00.000000", "1900-02-28 00:00:00.000000", "1900-03-01 00:00:00.000000", "9999-12-31 00:00:00.000000", "1969-12-31 00:00:00.000000", "1970-01-01 00:00:00.000000", null] ["0000-01-01 00:00:00.000000", "9999-12-31 00:00:00.000000", "2020-02-29 00:00:00.000000", "2021-02-28 00:00:00.000000", "0000-12-13 00:00:00.000000"] @@ -11855,6 +12609,32 @@ NaN [] [] +-- !sql_array_remove_TimestampNs_notnull -- +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null] +[null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +[null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] + -- !sql_array_remove_DateV2 -- \N \N @@ -12557,6 +13337,32 @@ NaN [null] [null] +-- !sql_array_reverse_sort_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", null, null, null, null, null, null, null, null] +["2021-12-31 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", null, null, null] +["2021-12-31 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-02-28 00:00:00.000000000", "1970-01-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", null, null, null, null, null, null, null, null, null, null, null] +["2021-12-31 00:00:00.000000000"] +[] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_reverse_sort_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000"] ["0000-12-13 00:00:00.000000"] @@ -12583,6 +13389,32 @@ NaN [null] [null] +-- !sql_array_reverse_sort_TimestampNs_notnull -- +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", null, null, null, null, null, null, null, null] +["2021-12-31 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", null, null, null] +["2021-12-31 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-02-28 00:00:00.000000000", "1970-01-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", null, null, null, null, null, null, null, null, null, null, null] +["2021-12-31 00:00:00.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_reverse_sort_DateV2 -- \N \N @@ -12687,7 +13519,61 @@ NaN [] [] --- !sql_array_slice_Float -- +-- !sql_array_slice_Float -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +[16] +[] +[] +[] +[] +[] + +-- !sql_array_slice_Float_notnull -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +[16] +[] +[] +[] +[] +[] + +-- !sql_array_slice_LargeInt -- +\N +\N \N \N \N @@ -12710,10 +13596,8 @@ NaN [] [] [] -[] -[] --- !sql_array_slice_Float_notnull -- +-- !sql_array_slice_LargeInt_notnull -- \N \N \N @@ -12739,9 +13623,7 @@ NaN [] [] --- !sql_array_slice_LargeInt -- -\N -\N +-- !sql_array_slice_BigInt -- \N \N \N @@ -12764,8 +13646,10 @@ NaN [] [] [] +[] +[] --- !sql_array_slice_LargeInt_notnull -- +-- !sql_array_slice_BigInt_notnull -- \N \N \N @@ -12791,7 +13675,7 @@ NaN [] [] --- !sql_array_slice_BigInt -- +-- !sql_array_slice_SmallInt -- \N \N \N @@ -12817,7 +13701,7 @@ NaN [] [] --- !sql_array_slice_BigInt_notnull -- +-- !sql_array_slice_SmallInt_notnull -- \N \N \N @@ -12843,7 +13727,7 @@ NaN [] [] --- !sql_array_slice_SmallInt -- +-- !sql_array_slice_Integer -- \N \N \N @@ -12869,7 +13753,7 @@ NaN [] [] --- !sql_array_slice_SmallInt_notnull -- +-- !sql_array_slice_Integer_notnull -- \N \N \N @@ -12895,7 +13779,7 @@ NaN [] [] --- !sql_array_slice_Integer -- +-- !sql_array_slice_TinyInt -- \N \N \N @@ -12921,7 +13805,7 @@ NaN [] [] --- !sql_array_slice_Integer_notnull -- +-- !sql_array_slice_TinyInt_notnull -- \N \N \N @@ -12947,7 +13831,10 @@ NaN [] [] --- !sql_array_slice_TinyInt -- +-- !sql_array_slice_DecimalV3 -- +\N +\N +\N \N \N \N @@ -12966,14 +13853,11 @@ NaN \N \N \N -[16] -[] -[] [] [] [] --- !sql_array_slice_TinyInt_notnull -- +-- !sql_array_slice_DecimalV3_notnull -- \N \N \N @@ -12992,14 +13876,17 @@ NaN \N \N \N -[16] +[] [] [] [] [] [] --- !sql_array_slice_DecimalV3 -- +-- !sql_array_slice_Boolean -- +\N +\N +\N \N \N \N @@ -13021,11 +13908,8 @@ NaN \N \N \N -[] -[] -[] --- !sql_array_slice_DecimalV3_notnull -- +-- !sql_array_slice_Boolean_notnull -- \N \N \N @@ -13051,10 +13935,7 @@ NaN [] [] --- !sql_array_slice_Boolean -- -\N -\N -\N +-- !sql_array_slice_Char -- \N \N \N @@ -13076,8 +13957,11 @@ NaN \N \N \N +[] +[] +[] --- !sql_array_slice_Boolean_notnull -- +-- !sql_array_slice_Char_notnull -- \N \N \N @@ -13103,7 +13987,7 @@ NaN [] [] --- !sql_array_slice_Char -- +-- !sql_array_slice_Varchar -- \N \N \N @@ -13129,7 +14013,7 @@ NaN [] [] --- !sql_array_slice_Char_notnull -- +-- !sql_array_slice_Varchar_notnull -- \N \N \N @@ -13155,7 +14039,7 @@ NaN [] [] --- !sql_array_slice_Varchar -- +-- !sql_array_slice_String -- \N \N \N @@ -13181,7 +14065,7 @@ NaN [] [] --- !sql_array_slice_Varchar_notnull -- +-- !sql_array_slice_String_notnull -- \N \N \N @@ -13207,10 +14091,7 @@ NaN [] [] --- !sql_array_slice_String -- -\N -\N -\N +-- !sql_array_slice_DatetimeV2 -- \N \N \N @@ -13229,11 +14110,14 @@ NaN \N \N \N +["2021-02-28 00:00:00.000000"] +[] +[] [] [] [] --- !sql_array_slice_String_notnull -- +-- !sql_array_slice_TimestampNs -- \N \N \N @@ -13252,14 +14136,14 @@ NaN \N \N \N -[] +["2021-02-28 00:00:00.000000000"] [] [] [] [] [] --- !sql_array_slice_DatetimeV2 -- +-- !sql_array_slice_DatetimeV2_notnull -- \N \N \N @@ -13285,7 +14169,7 @@ NaN [] [] --- !sql_array_slice_DatetimeV2_notnull -- +-- !sql_array_slice_TimestampNs_notnull -- \N \N \N @@ -13304,7 +14188,7 @@ NaN \N \N \N -["2021-02-28 00:00:00.000000"] +["2021-02-28 00:00:00.000000000"] [] [] [] @@ -14013,6 +14897,32 @@ NaN [] [] +-- !sql_array_slice_three_params_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +[] +[] +[] +[] +[] +[] + -- !sql_array_slice_three_params_DatetimeV2_notnull -- \N \N @@ -14039,6 +14949,32 @@ NaN [] [] +-- !sql_array_slice_three_params_TimestampNs_notnull -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +[] +[] +[] +[] +[] +[] + -- !sql_array_slice_three_params_DateV2 -- \N \N @@ -14741,6 +15677,32 @@ NaN [null] [null] +-- !sql_array_sort_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000"] +[] +[null, null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, null, null, null, null, null, null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, null, null, null, null, null, null, null, null, null, null, "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_sort_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000", "0000-12-13 00:00:00.000000", "2020-02-29 00:00:00.000000", "2021-02-28 00:00:00.000000", "2021-12-31 00:00:00.000000", "9999-12-31 00:00:00.000000"] ["0000-01-01 00:00:00.000000"] @@ -14767,6 +15729,32 @@ NaN [null] [null] +-- !sql_array_sort_TimestampNs_notnull -- +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null, null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, null, null, null, null, null, null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, null, null, null, null, null, null, null, null, null, null, "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_sort_DateV2 -- \N \N @@ -15885,6 +16873,32 @@ NaN [null] [null] +-- !sql_array_union_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000"] +[] +[null, "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_union_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000", "0000-12-13 00:00:00.000000", "2020-02-29 00:00:00.000000", "2021-02-28 00:00:00.000000", "2021-12-31 00:00:00.000000", "9999-12-31 00:00:00.000000"] ["0000-01-01 00:00:00.000000"] @@ -15911,6 +16925,32 @@ NaN [null] [null] +-- !sql_array_union_TimestampNs_notnull -- +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null, "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_union_DateV2 -- \N \N @@ -16613,6 +17653,32 @@ NaN 21 6 +-- !sql_cardinality_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +11 +21 +6 + -- !sql_cardinality_DatetimeV2_notnull -- 0 0 @@ -16639,6 +17705,32 @@ NaN 21 6 +-- !sql_cardinality_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +11 +21 +6 + -- !sql_cardinality_DateV2 -- \N \N @@ -17341,6 +18433,32 @@ NaN 21 6 +-- !sql_array_size_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +11 +21 +6 + -- !sql_array_size_DatetimeV2_notnull -- 0 0 @@ -17367,6 +18485,32 @@ NaN 21 6 +-- !sql_array_size_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +11 +21 +6 + -- !sql_array_size_DateV2 -- \N \N @@ -18069,6 +19213,32 @@ NaN 21 6 +-- !sql_size_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +11 +21 +6 + -- !sql_size_DatetimeV2_notnull -- 0 0 @@ -18095,6 +19265,32 @@ NaN 21 6 +-- !sql_size_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +11 +21 +6 + -- !sql_size_DateV2 -- \N \N @@ -25037,6 +26233,32 @@ true [null] [null] +-- !sql_array_compact_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000"] +[] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_compact_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000"] ["0000-12-13 00:00:00.000000"] @@ -25063,6 +26285,32 @@ true [null] [null] +-- !sql_array_compact_TimestampNs_notnull -- +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_compact_DateV2 -- \N \N @@ -25765,6 +27013,32 @@ true [null, null] [null, null] +-- !sql_array_concat_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2020-02-29 00:00:00.000000000", "2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, "2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null, "2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null] +["2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null, "2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] +[] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] + -- !sql_array_concat_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000", "0000-01-01 00:00:00.000000"] ["0000-12-13 00:00:00.000000", "0000-12-13 00:00:00.000000"] @@ -25791,6 +27065,32 @@ true [null, null] [null, null] +-- !sql_array_concat_TimestampNs_notnull -- +["2020-02-29 00:00:00.000000000", "2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, "2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null, "2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null] +["2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null, "2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] + -- !sql_array_concat_DateV2 -- \N \N @@ -27117,6 +28417,32 @@ true [null] [null] +-- !sql_array_distinct_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000"] +[] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_distinct_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000"] ["0000-12-13 00:00:00.000000"] @@ -27143,6 +28469,32 @@ true [null] [null] +-- !sql_array_distinct_TimestampNs_notnull -- +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_distinct_DateV2 -- \N \N @@ -27663,7 +29015,64 @@ true [] [] --- !sql_array_except_DecimalV3 -- +-- !sql_array_except_DecimalV3 -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +[] +[] +[] +[] +[] + +-- !sql_array_except_DecimalV3_notnull -- +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] + +-- !sql_array_except_Boolean -- +\N +\N +\N +\N +\N \N \N \N @@ -27683,13 +29092,8 @@ true \N \N \N -[] -[] -[] -[] -[] --- !sql_array_except_DecimalV3_notnull -- +-- !sql_array_except_Boolean_notnull -- [] [] [] @@ -27715,12 +29119,7 @@ true [] [] --- !sql_array_except_Boolean -- -\N -\N -\N -\N -\N +-- !sql_array_except_Char -- \N \N \N @@ -27740,8 +29139,13 @@ true \N \N \N +[] +[] +[] +[] +[] --- !sql_array_except_Boolean_notnull -- +-- !sql_array_except_Char_notnull -- [] [] [] @@ -27767,7 +29171,7 @@ true [] [] --- !sql_array_except_Char -- +-- !sql_array_except_Varchar -- \N \N \N @@ -27793,7 +29197,7 @@ true [] [] --- !sql_array_except_Char_notnull -- +-- !sql_array_except_Varchar_notnull -- [] [] [] @@ -27819,7 +29223,7 @@ true [] [] --- !sql_array_except_Varchar -- +-- !sql_array_except_String -- \N \N \N @@ -27845,7 +29249,7 @@ true [] [] --- !sql_array_except_Varchar_notnull -- +-- !sql_array_except_String_notnull -- [] [] [] @@ -27871,10 +29275,7 @@ true [] [] --- !sql_array_except_String -- -\N -\N -\N +-- !sql_array_except_DatetimeV2 -- \N \N \N @@ -27883,6 +29284,24 @@ true \N \N \N +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] + +-- !sql_array_except_TimestampNs -- \N \N \N @@ -27896,13 +29315,6 @@ true [] [] [] - --- !sql_array_except_String_notnull -- -[] -[] -[] -[] -[] [] [] [] @@ -27914,6 +29326,8 @@ true [] [] [] + +-- !sql_array_except_DatetimeV2_notnull -- [] [] [] @@ -27922,16 +29336,6 @@ true [] [] [] - --- !sql_array_except_DatetimeV2 -- -\N -\N -\N -\N -\N -\N -\N -\N [] [] [] @@ -27949,7 +29353,7 @@ true [] [] --- !sql_array_except_DatetimeV2_notnull -- +-- !sql_array_except_TimestampNs_notnull -- [] [] [] @@ -28677,6 +30081,32 @@ true [null] [null] +-- !sql_array_intersect_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000"] +[] +[null, "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_intersect_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000", "0000-12-13 00:00:00.000000", "2020-02-29 00:00:00.000000", "2021-02-28 00:00:00.000000", "2021-12-31 00:00:00.000000", "9999-12-31 00:00:00.000000"] ["0000-01-01 00:00:00.000000"] @@ -28703,6 +30133,32 @@ true [null] [null] +-- !sql_array_intersect_TimestampNs_notnull -- +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null, "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_intersect_DateV2 -- \N \N @@ -29405,6 +30861,32 @@ null null null +-- !sql_array_join_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N + +2020-02-29 00:00:00.000000000 +2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000,null,null,2020-02-29 00:00:00.000000000,2021-02-28 00:00:00.000000000,null +2021-12-31 00:00:00.000000000,null,null,2020-02-29 00:00:00.000000000,2021-02-28 00:00:00.000000000,null,null,null,null,null,null +2021-12-31 00:00:00.000000000,null,null,null,null,null,null,null,null,null,2020-02-28 00:00:00.000000000,2020-02-29 00:00:00.000000000,2020-03-01 00:00:00.000000000,2021-02-28 00:00:00.000000000,2021-03-01 00:00:00.000000000,1900-02-28 00:00:00.000000000,1900-03-01 00:00:00.000000000,null,1969-12-31 00:00:00.000000000,1970-01-01 00:00:00.000000000,null +null +null +null +null +null +null +null +null +null + -- !sql_array_join_DatetimeV2_notnull -- @@ -29431,6 +30913,32 @@ null null null +-- !sql_array_join_TimestampNs_notnull -- + + + + + + + + + +2020-02-29 00:00:00.000000000 +2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000,null,null,2020-02-29 00:00:00.000000000,2021-02-28 00:00:00.000000000,null +2021-12-31 00:00:00.000000000,null,null,2020-02-29 00:00:00.000000000,2021-02-28 00:00:00.000000000,null,null,null,null,null,null +2021-12-31 00:00:00.000000000,null,null,null,null,null,null,null,null,null,2020-02-28 00:00:00.000000000,2020-02-29 00:00:00.000000000,2020-03-01 00:00:00.000000000,2021-02-28 00:00:00.000000000,2021-03-01 00:00:00.000000000,1900-02-28 00:00:00.000000000,1900-03-01 00:00:00.000000000,null,1969-12-31 00:00:00.000000000,1970-01-01 00:00:00.000000000,null +null +null +null +null +null +null +null +null +null + -- !sql_array_join_DateV2 -- \N \N @@ -30133,6 +31641,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 2021-12-31 00:00:00.000000,0000-01-01 00:00:00.000000,9999-12-31 00:00:00.000000,2020-02-29 00:00:00.000000,2021-02-28 00:00:00.000000,0000-12-13 00:00:00.000000 9999-12-31 00:00:00.000000 +-- !sql_array_join_two_params_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N + + + + + + + + + + +2020-02-29 00:00:00.000000000 +2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000,2020-02-28 00:00:00.000000000,2020-02-29 00:00:00.000000000,2020-03-01 00:00:00.000000000,2021-02-28 00:00:00.000000000,2021-03-01 00:00:00.000000000,1900-02-28 00:00:00.000000000,1900-03-01 00:00:00.000000000,1969-12-31 00:00:00.000000000,1970-01-01 00:00:00.000000000 +2021-12-31 00:00:00.000000000,2020-02-29 00:00:00.000000000,2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000,2020-02-29 00:00:00.000000000,2021-02-28 00:00:00.000000000 + -- !sql_array_join_two_params_DatetimeV2_notnull -- @@ -30159,6 +31693,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 2021-12-31 00:00:00.000000,0000-01-01 00:00:00.000000,9999-12-31 00:00:00.000000,2020-02-29 00:00:00.000000,2021-02-28 00:00:00.000000,0000-12-13 00:00:00.000000 9999-12-31 00:00:00.000000 +-- !sql_array_join_two_params_TimestampNs_notnull -- + + + + + + + + + + + + + + + + + + +2020-02-29 00:00:00.000000000 +2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000,2020-02-28 00:00:00.000000000,2020-02-29 00:00:00.000000000,2020-03-01 00:00:00.000000000,2021-02-28 00:00:00.000000000,2021-03-01 00:00:00.000000000,1900-02-28 00:00:00.000000000,1900-03-01 00:00:00.000000000,1969-12-31 00:00:00.000000000,1970-01-01 00:00:00.000000000 +2021-12-31 00:00:00.000000000,2020-02-29 00:00:00.000000000,2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000,2020-02-29 00:00:00.000000000,2021-02-28 00:00:00.000000000 + -- !sql_array_join_two_params_DateV2 -- \N \N @@ -30705,6 +32265,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 9999-12-31T00:00 9999-12-31T00:00 +-- !sql_array_max_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +2020-02-29 00:00:00.000000000 +2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000 + -- !sql_array_max_DatetimeV2_notnull -- \N \N @@ -30731,6 +32317,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 9999-12-31T00:00 9999-12-31T00:00 +-- !sql_array_max_TimestampNs_notnull -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +2020-02-29 00:00:00.000000000 +2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000 +2021-12-31 00:00:00.000000000 + -- !sql_array_max_DateV2 -- \N \N @@ -31277,6 +32889,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 2021-12-31T00:00 9999-12-31T00:00 +-- !sql_array_min_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +1900-02-28 00:00:00.000000000 +2020-02-29 00:00:00.000000000 +2020-02-29 00:00:00.000000000 +2020-02-29 00:00:00.000000000 +2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000 + -- !sql_array_min_DatetimeV2_notnull -- \N \N @@ -31303,6 +32941,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 2021-12-31T00:00 9999-12-31T00:00 +-- !sql_array_min_TimestampNs_notnull -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +1900-02-28 00:00:00.000000000 +2020-02-29 00:00:00.000000000 +2020-02-29 00:00:00.000000000 +2020-02-29 00:00:00.000000000 +2021-02-28 00:00:00.000000000 +2021-12-31 00:00:00.000000000 + -- !sql_array_min_DateV2 -- \N \N @@ -32005,6 +33669,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 [] [] +-- !sql_array_popback_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] + -- !sql_array_popback_DatetimeV2_notnull -- ["2021-12-31 00:00:00.000000", "0000-01-01 00:00:00.000000", "0000-01-02 00:00:00.000000", "0000-01-03 00:00:00.000000", "0000-01-04 00:00:00.000000", "0000-01-05 00:00:00.000000", "0000-01-06 00:00:00.000000", "0000-01-07 00:00:00.000000", "0000-12-31 00:00:00.000000", "0000-02-28 00:00:00.000000", "2020-02-28 00:00:00.000000", "2020-02-29 00:00:00.000000", "2020-03-01 00:00:00.000000", "2021-02-28 00:00:00.000000", "2021-03-01 00:00:00.000000", "1900-02-28 00:00:00.000000", "1900-03-01 00:00:00.000000", "9999-12-31 00:00:00.000000", "1969-12-31 00:00:00.000000", "1970-01-01 00:00:00.000000"] ["2021-12-31 00:00:00.000000", "0000-01-01 00:00:00.000000", "9999-12-31 00:00:00.000000", "2020-02-29 00:00:00.000000", "2021-02-28 00:00:00.000000", null, null, null, "0000-12-13 00:00:00.000000", null] @@ -32031,6 +33721,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 [] [] +-- !sql_array_popback_TimestampNs_notnull -- +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] + -- !sql_array_popback_DateV2 -- \N \N @@ -32733,6 +34449,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 [] [] +-- !sql_array_popfront_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null] +[null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +[null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] + -- !sql_array_popfront_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000", "0000-01-02 00:00:00.000000", "0000-01-03 00:00:00.000000", "0000-01-04 00:00:00.000000", "0000-01-05 00:00:00.000000", "0000-01-06 00:00:00.000000", "0000-01-07 00:00:00.000000", "0000-12-31 00:00:00.000000", "0000-02-28 00:00:00.000000", "2020-02-28 00:00:00.000000", "2020-02-29 00:00:00.000000", "2020-03-01 00:00:00.000000", "2021-02-28 00:00:00.000000", "2021-03-01 00:00:00.000000", "1900-02-28 00:00:00.000000", "1900-03-01 00:00:00.000000", "9999-12-31 00:00:00.000000", "1969-12-31 00:00:00.000000", "1970-01-01 00:00:00.000000", null] ["0000-01-01 00:00:00.000000", "9999-12-31 00:00:00.000000", "2020-02-29 00:00:00.000000", "2021-02-28 00:00:00.000000", "0000-12-13 00:00:00.000000"] @@ -32759,6 +34501,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 [] [] +-- !sql_array_popfront_TimestampNs_notnull -- +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null] +[null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +[null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] + -- !sql_array_popfront_DateV2 -- \N \N @@ -33409,6 +35177,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 1 1 +-- !sql_array_position_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 + -- !sql_array_position_DatetimeV2_notnull -- 0 0 @@ -33435,6 +35229,32 @@ aaaaa,12345!@#$%^&*()_,,中文测试,123,abs ss 123,[{"_id":"667d1d6d78d92a8df53 1 1 +-- !sql_array_position_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 + -- !sql_array_position_DateV2 -- \N \N @@ -34345,6 +36165,32 @@ NaN [null, null] [null] +-- !sql_array_pushback_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2020-02-29 00:00:00.000000000", "2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, "2021-12-31 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null, "2021-12-31 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null, "2021-12-31 00:00:00.000000000"] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null] + -- !sql_array_pushback_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000", "0000-01-01 00:00:00.000000"] ["0000-12-13 00:00:00.000000", "0000-12-13 00:00:00.000000"] @@ -34371,6 +36217,32 @@ NaN [null] [null] +-- !sql_array_pushback_TimestampNs_notnull -- +["2020-02-29 00:00:00.000000000", "2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, "2021-12-31 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null, "2021-12-31 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null, "2021-12-31 00:00:00.000000000"] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_pushback_DateV2 -- \N \N @@ -35073,6 +36945,32 @@ NaN [null, null] [null] +-- !sql_array_pushfront_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2020-02-29 00:00:00.000000000", "2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null] + -- !sql_array_pushfront_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000", "0000-01-01 00:00:00.000000"] ["0000-12-13 00:00:00.000000", "0000-12-13 00:00:00.000000"] @@ -35099,6 +36997,32 @@ NaN [null] [null] +-- !sql_array_pushfront_TimestampNs_notnull -- +["2020-02-29 00:00:00.000000000", "2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000", "2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000", null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000", null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] +["2021-12-31 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null, null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_pushfront_DateV2 -- \N \N @@ -35567,12 +37491,59 @@ NaN [] [] --- !sql_array_remove_Boolean -- -\N -\N -\N -\N -\N +-- !sql_array_remove_Boolean -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N + +-- !sql_array_remove_Boolean_notnull -- +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] + +-- !sql_array_remove_Char -- \N \N \N @@ -35592,11 +37563,16 @@ NaN \N \N \N - --- !sql_array_remove_Boolean_notnull -- +["'aaaaa", "12345! @#$ %^ &*()_", "d\\d", "\\", "\\aacdefghijklm\nopq\rs\ uvwxyzABCDEFGHIJKLMNOPQRSTUVWXY", "REPEAT('1',20)", "中文测试", "123", "abs ss 123", "C:UsersUsernameDocumentsfile.txt", "/home/username/documents/file.txt", "test@example.com", "http://www.example.com", "https://www.example.com", "2023-04-30", "30/04/2023", "April 30, 2023", "Line 1: This is the first line of a multiline text.\nLine 2: This is the second line of a multiline text.\nLine 3: This is the third line of a multiline text.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl. Sed euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl.", "你好世界!こんにちは世界!안녕하세요 세계!", "SGVsbG8gV29ybGQh", "YW55IGNvbnRlbnQ=", "dGhpcyBpcyBhIHRlc3Q=", "Zm9vYmFy", "SGVsbG8gV29ybGQh!", "YW55IGNvbnRlbnQ==", "dGhpcyBpcyBhIHRlc3Q", "Zm9vYmFy==", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测"] +["0", "", "'aaaaa", "12345! @#$ %^ &*()_", "d\\d", "\\", "\\aacdefghijklm\nopq\rs\ uvwxyzABCDEFGHIJKLMNOPQRSTUVWXY", "", "REPEAT('1',20)", "中文测试", "123", "abs ss 123", "C:UsersUsernameDocumentsfile.txt", "/home/username/documents/file.txt", "test@example.com", "http://www.example.com", "https://www.example.com", "2023-04-30", "30/04/2023", "April 30, 2023", "Line 1: This is the first line of a multiline text.\nLine 2: This is the second line of a multiline text.\nLine 3: This is the third line of a multiline text.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl. Sed euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl.", "你好世界!こんにちは世界!안녕하세요 세계!", "SGVsbG8gV29ybGQh", "YW55IGNvbnRlbnQ=", "dGhpcyBpcyBhIHRlc3Q=", "Zm9vYmFy", "SGVsbG8gV29ybGQh!", "YW55IGNvbnRlbnQ==", "dGhpcyBpcyBhIHRlc3Q", "Zm9vYmFy==", "", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测"] [] [] [] + +-- !sql_array_remove_Char_notnull -- +["'aaaaa", "12345! @#$ %^ &*()_", "d\\d", "\\", "\\aacdefghijklm\nopq\rs\ uvwxyzABCDEFGHIJKLMNOPQRSTUVWXY", "REPEAT('1',20)", "中文测试", "123", "abs ss 123", "C:UsersUsernameDocumentsfile.txt", "/home/username/documents/file.txt", "test@example.com", "http://www.example.com", "https://www.example.com", "2023-04-30", "30/04/2023", "April 30, 2023", "Line 1: This is the first line of a multiline text.\nLine 2: This is the second line of a multiline text.\nLine 3: This is the third line of a multiline text.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl. Sed euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl.", "你好世界!こんにちは世界!안녕하세요 세계!", "SGVsbG8gV29ybGQh", "YW55IGNvbnRlbnQ=", "dGhpcyBpcyBhIHRlc3Q=", "Zm9vYmFy", "SGVsbG8gV29ybGQh!", "YW55IGNvbnRlbnQ==", "dGhpcyBpcyBhIHRlc3Q", "Zm9vYmFy==", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测"] +["0", "", "'aaaaa", "12345! @#$ %^ &*()_", "d\\d", "\\", "\\aacdefghijklm\nopq\rs\ uvwxyzABCDEFGHIJKLMNOPQRSTUVWXY", "", "REPEAT('1',20)", "中文测试", "123", "abs ss 123", "C:UsersUsernameDocumentsfile.txt", "/home/username/documents/file.txt", "test@example.com", "http://www.example.com", "https://www.example.com", "2023-04-30", "30/04/2023", "April 30, 2023", "Line 1: This is the first line of a multiline text.\nLine 2: This is the second line of a multiline text.\nLine 3: This is the third line of a multiline text.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl. Sed euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl.", "你好世界!こんにちは世界!안녕하세요 세계!", "SGVsbG8gV29ybGQh", "YW55IGNvbnRlbnQ=", "dGhpcyBpcyBhIHRlc3Q=", "Zm9vYmFy", "SGVsbG8gV29ybGQh!", "YW55IGNvbnRlbnQ==", "dGhpcyBpcyBhIHRlc3Q", "Zm9vYmFy==", "", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测"] +[] [] [] [] @@ -35619,7 +37595,7 @@ NaN [] [] --- !sql_array_remove_Char -- +-- !sql_array_remove_Varchar -- \N \N \N @@ -35639,15 +37615,15 @@ NaN \N \N \N -["'aaaaa", "12345! @#$ %^ &*()_", "d\\d", "\\", "\\aacdefghijklm\nopq\rs\ uvwxyzABCDEFGHIJKLMNOPQRSTUVWXY", "REPEAT('1',20)", "中文测试", "123", "abs ss 123", "C:UsersUsernameDocumentsfile.txt", "/home/username/documents/file.txt", "test@example.com", "http://www.example.com", "https://www.example.com", "2023-04-30", "30/04/2023", "April 30, 2023", "Line 1: This is the first line of a multiline text.\nLine 2: This is the second line of a multiline text.\nLine 3: This is the third line of a multiline text.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl. Sed euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl.", "你好世界!こんにちは世界!안녕하세요 세계!", "SGVsbG8gV29ybGQh", "YW55IGNvbnRlbnQ=", "dGhpcyBpcyBhIHRlc3Q=", "Zm9vYmFy", "SGVsbG8gV29ybGQh!", "YW55IGNvbnRlbnQ==", "dGhpcyBpcyBhIHRlc3Q", "Zm9vYmFy==", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测"] -["0", "", "'aaaaa", "12345! @#$ %^ &*()_", "d\\d", "\\", "\\aacdefghijklm\nopq\rs\ uvwxyzABCDEFGHIJKLMNOPQRSTUVWXY", "", "REPEAT('1',20)", "中文测试", "123", "abs ss 123", "C:UsersUsernameDocumentsfile.txt", "/home/username/documents/file.txt", "test@example.com", "http://www.example.com", "https://www.example.com", "2023-04-30", "30/04/2023", "April 30, 2023", "Line 1: This is the first line of a multiline text.\nLine 2: This is the second line of a multiline text.\nLine 3: This is the third line of a multiline text.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl. Sed euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl.", "你好世界!こんにちは世界!안녕하세요 세계!", "SGVsbG8gV29ybGQh", "YW55IGNvbnRlbnQ=", "dGhpcyBpcyBhIHRlc3Q=", "Zm9vYmFy", "SGVsbG8gV29ybGQh!", "YW55IGNvbnRlbnQ==", "dGhpcyBpcyBhIHRlc3Q", "Zm9vYmFy==", "", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测"] +["12345! @#$ %^ &*()_", "d\\d", "\\", "\\aacdefghijklm\nopq\rs\ uvwxyzABCDEFGHIJKLMNOPQRSTUVWXY", "", "REPEAT('1',20)", "中文测试", "123", "abs ss 123", "C:UsersUsernameDocumentsfile.txt", "/home/username/documents/file.txt", "test@example.com", "http://www.example.com", "https://www.example.com", "2023-04-30", "30/04/2023", "April 30, 2023", "Line 1: This is the first line of a multiline text.\nLine 2: This is the second line of a multiline text.\nLine 3: This is the third line of a multiline text.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl. Sed euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl.", "你好世界!こんにちは世界!안녕하세요 세계!", "SGVsbG8gV29ybGQh", "YW55IGNvbnRlbnQ=", "dGhpcyBpcyBhIHRlc3Q=", "Zm9vYmFy", "SGVsbG8gV29ybGQh!", "YW55IGNvbnRlbnQ==", "dGhpcyBpcyBhIHRlc3Q", "Zm9vYmFy==", "[{"_id":"667d1d6d78d92a8df5349ae8","index":0,"guid":"5e2e76b2-b2d4-477a-8962-4c36e554c21d","isActive":false,"balance":"$1,228.18","picture":"http://placehold.it/32x32","age":22,"eyeColor":"green","name":"Diane Harrington","gender":"female","company":"SUPPORTAL","email":"dianeharrington@supportal.com","phone":"+1 (990) 563-2570","address":"866 Cheever Place, Caln, Tennessee, 992","about":"Nulla est velit adipisicing labore labore anim et aute culpa aliqua cupidatat. Anim laborum proident consequat est duis ea deserunt cupidatat exercitation ea qui dolor. Veniam nostrud aliqua pariatur ipsum. Nisi cupidatat eu ipsum ut consectetur irure sint laborum dolore nostrud dolore ipsum. Anim irure anim cillum mollit ex reprehenderit commodo. Adipisicing reprehenderit sit qui eiusmod dolore nostrud commodo proident minim ut ut deserunt ullamco.\r\n","registered":"2019-02-08T05:19:25 -08:00","latitude":12.029664,"longitude":164.711199,"tags":["exercitation","est","consequat","irure","laborum","cillum","irure"],"friends":[{"id":0,"name":"Murray Johns"},{"id":1,"name":"Crane Hutchinson"},{"id":2,"name":"Wynn Castro"}],"greeting":"Hello, Diane Harrington! You have 7 unread messages.","favoriteFruit":"apple"}]", "[{"_id":"667d1d827fb270ffd9678130","index":0,"guid":"cba8a7b5-89d8-46ec-a6b8-68c6ad014ee1","isActive":true,"balance":"$1,286.08","picture":"http://placehold.it/32x32","age":26,"eyeColor":"green","name":"Barrett Zimmerman","gender":"male","company":"ZYTRAX","email":"barrettzimmerman@zytrax.com","phone":"+1 (980) 433-2997","address":"347 Logan Street, Cascades, Colorado, 8222","about":"Excepteur laborum qui consectetur enim non id ex id. Id ut officia fugiat nulla non minim irure adipisicing magna do occaecat reprehenderit duis duis. Quis quis dolor adipisicing nostrud reprehenderit nulla duis Lorem in eu Lorem.\r\n","registered":"2018-05-30T01:12:48 -08:00","latitude":-12.380399,"longitude":29.630323,"tags":["esse","nulla","irure","est","voluptate","nisi","consequat"],"friends":[{"id":0,"name":"Guy Haynes"},{"id":1,"name":"Aguirre Waller"},{"id":2,"name":"Freeman Parsons"}],"greeting":"Hello, Barrett Zimmerman! You have 4 unread messages.","favoriteFruit":"banana"},{"_id":"667d1d820979330df1da0945","index":1,"guid":"52484521-7816-4501-b278-b0f93005fbba","isActive":false,"balance":"$3,163.35","picture":"http://placehold.it/32x32","age":31,"eyeColor":"blue","name":"Jenny Shannon","gender":"female","company":"EPLOSION","email":"jennyshannon@eplosion.com","phone":"+1 (959) 554-2872","address":"909 Brighton Avenue, Cochranville, Iowa, 7261","about":"Dolor ipsum laborum fugiat ipsum tempor minim excepteur dolore esse irure. Ut sunt esse minim consequat est irure amet veniam ullamco. Commodo sit est eiusmod adipisicing deserunt incididunt ad. Consectetur commodo ea id aliquip ipsum velit culpa adipisicing. Sint nostrud ullamco duis et dolor magna laborum nisi ut ad adipisicing ut id tempor. Anim laborum qui ea sunt enim.\r\n","registered":"2016-09-27T04:10:16 -08:00","latitude":-18.507749,"longitude":60.414486,"tags":["duis","veniam","tempor","cillum","anim","sunt","proident"],"friends":[{"id":0,"name":"Herminia Silva"},{"id":1,"name":"Terrie Mckinney"},{"id":2,"name":"Valentine Richardson"}],"greeting":"Hello, Jenny Shannon! You have 2 unread messages.","favoriteFruit":"apple"}]", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试"] +["aaaaa", "12345!@#$%^&*()_", "", "中文测试", "123", "abs ss 123", "[{"_id":"667d1d6d78d92a8df5349ae8","index":0,"guid":"5e2e76b2-b2d4-477a-8962-4c36e554c21d","isActive":false,"balance":"$1,228.18","picture":"http://placehold.it/32x32","age":22,"eyeColor":"green","name":"Diane Harrington","gender":"female","company":"SUPPORTAL","email":"dianeharrington@supportal.com","phone":"+1 (990) 563-2570","address":"866 Cheever Place, Caln, Tennessee, 992","about":"Nulla est velit adipisicing labore labore anim et aute culpa aliqua cupidatat. Anim laborum proident consequat est duis ea deserunt cupidatat exercitation ea qui dolor. Veniam nostrud aliqua pariatur ipsum. Nisi cupidatat eu ipsum ut consectetur irure sint laborum dolore nostrud dolore ipsum. Anim irure anim cillum mollit ex reprehenderit commodo. Adipisicing reprehenderit sit qui eiusmod dolore nostrud commodo proident minim ut ut deserunt ullamco.\r\n","registered":"2019-02-08T05:19:25 -08:00","latitude":12.029664,"longitude":164.711199,"tags":["exercitation","est","consequat","irure","laborum","cillum","irure"],"friends":[{"id":0,"name":"Murray Johns"},{"id":1,"name":"Crane Hutchinson"},{"id":2,"name":"Wynn Castro"}],"greeting":"Hello, Diane Harrington! You have 7 unread messages.","favoriteFruit":"apple"}]", "[{"_id":"667d1d827fb270ffd9678130","index":0,"guid":"cba8a7b5-89d8-46ec-a6b8-68c6ad014ee1","isActive":true,"balance":"$1,286.08","picture":"http://placehold.it/32x32","age":26,"eyeColor":"green","name":"Barrett Zimmerman","gender":"male","company":"ZYTRAX","email":"barrettzimmerman@zytrax.com","phone":"+1 (980) 433-2997","address":"347 Logan Street, Cascades, Colorado, 8222","about":"Excepteur laborum qui consectetur enim non id ex id. Id ut officia fugiat nulla non minim irure adipisicing magna do occaecat reprehenderit duis duis. Quis quis dolor adipisicing nostrud reprehenderit nulla duis Lorem in eu Lorem.\r\n","registered":"2018-05-30T01:12:48 -08:00","latitude":-12.380399,"longitude":29.630323,"tags":["esse","nulla","irure","est","voluptate","nisi","consequat"],"friends":[{"id":0,"name":"Guy Haynes"},{"id":1,"name":"Aguirre Waller"},{"id":2,"name":"Freeman Parsons"}],"greeting":"Hello, Barrett Zimmerman! You have 4 unread messages.","favoriteFruit":"banana"},{"_id":"667d1d820979330df1da0945","index":1,"guid":"52484521-7816-4501-b278-b0f93005fbba","isActive":false,"balance":"$3,163.35","picture":"http://placehold.it/32x32","age":31,"eyeColor":"blue","name":"Jenny Shannon","gender":"female","company":"EPLOSION","email":"jennyshannon@eplosion.com","phone":"+1 (959) 554-2872","address":"909 Brighton Avenue, Cochranville, Iowa, 7261","about":"Dolor ipsum laborum fugiat ipsum tempor minim excepteur dolore esse irure. Ut sunt esse minim consequat est irure amet veniam ullamco. Commodo sit est eiusmod adipisicing deserunt incididunt ad. Consectetur commodo ea id aliquip ipsum velit culpa adipisicing. Sint nostrud ullamco duis et dolor magna laborum nisi ut ad adipisicing ut id tempor. Anim laborum qui ea sunt enim.\r\n","registered":"2016-09-27T04:10:16 -08:00","latitude":-18.507749,"longitude":60.414486,"tags":["duis","veniam","tempor","cillum","anim","sunt","proident"],"friends":[{"id":0,"name":"Herminia Silva"},{"id":1,"name":"Terrie Mckinney"},{"id":2,"name":"Valentine Richardson"}],"greeting":"Hello, Jenny Shannon! You have 2 unread messages.","favoriteFruit":"apple"}]", "aaaaaaaxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试"] [] [] [] --- !sql_array_remove_Char_notnull -- -["'aaaaa", "12345! @#$ %^ &*()_", "d\\d", "\\", "\\aacdefghijklm\nopq\rs\ uvwxyzABCDEFGHIJKLMNOPQRSTUVWXY", "REPEAT('1',20)", "中文测试", "123", "abs ss 123", "C:UsersUsernameDocumentsfile.txt", "/home/username/documents/file.txt", "test@example.com", "http://www.example.com", "https://www.example.com", "2023-04-30", "30/04/2023", "April 30, 2023", "Line 1: This is the first line of a multiline text.\nLine 2: This is the second line of a multiline text.\nLine 3: This is the third line of a multiline text.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl. Sed euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl.", "你好世界!こんにちは世界!안녕하세요 세계!", "SGVsbG8gV29ybGQh", "YW55IGNvbnRlbnQ=", "dGhpcyBpcyBhIHRlc3Q=", "Zm9vYmFy", "SGVsbG8gV29ybGQh!", "YW55IGNvbnRlbnQ==", "dGhpcyBpcyBhIHRlc3Q", "Zm9vYmFy==", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测"] -["0", "", "'aaaaa", "12345! @#$ %^ &*()_", "d\\d", "\\", "\\aacdefghijklm\nopq\rs\ uvwxyzABCDEFGHIJKLMNOPQRSTUVWXY", "", "REPEAT('1',20)", "中文测试", "123", "abs ss 123", "C:UsersUsernameDocumentsfile.txt", "/home/username/documents/file.txt", "test@example.com", "http://www.example.com", "https://www.example.com", "2023-04-30", "30/04/2023", "April 30, 2023", "Line 1: This is the first line of a multiline text.\nLine 2: This is the second line of a multiline text.\nLine 3: This is the third line of a multiline text.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl. Sed euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl.", "你好世界!こんにちは世界!안녕하세요 세계!", "SGVsbG8gV29ybGQh", "YW55IGNvbnRlbnQ=", "dGhpcyBpcyBhIHRlc3Q=", "Zm9vYmFy", "SGVsbG8gV29ybGQh!", "YW55IGNvbnRlbnQ==", "dGhpcyBpcyBhIHRlc3Q", "Zm9vYmFy==", "", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测"] +-- !sql_array_remove_Varchar_notnull -- +["12345! @#$ %^ &*()_", "d\\d", "\\", "\\aacdefghijklm\nopq\rs\ uvwxyzABCDEFGHIJKLMNOPQRSTUVWXY", "", "REPEAT('1',20)", "中文测试", "123", "abs ss 123", "C:UsersUsernameDocumentsfile.txt", "/home/username/documents/file.txt", "test@example.com", "http://www.example.com", "https://www.example.com", "2023-04-30", "30/04/2023", "April 30, 2023", "Line 1: This is the first line of a multiline text.\nLine 2: This is the second line of a multiline text.\nLine 3: This is the third line of a multiline text.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl. Sed euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl.", "你好世界!こんにちは世界!안녕하세요 세계!", "SGVsbG8gV29ybGQh", "YW55IGNvbnRlbnQ=", "dGhpcyBpcyBhIHRlc3Q=", "Zm9vYmFy", "SGVsbG8gV29ybGQh!", "YW55IGNvbnRlbnQ==", "dGhpcyBpcyBhIHRlc3Q", "Zm9vYmFy==", "[{"_id":"667d1d6d78d92a8df5349ae8","index":0,"guid":"5e2e76b2-b2d4-477a-8962-4c36e554c21d","isActive":false,"balance":"$1,228.18","picture":"http://placehold.it/32x32","age":22,"eyeColor":"green","name":"Diane Harrington","gender":"female","company":"SUPPORTAL","email":"dianeharrington@supportal.com","phone":"+1 (990) 563-2570","address":"866 Cheever Place, Caln, Tennessee, 992","about":"Nulla est velit adipisicing labore labore anim et aute culpa aliqua cupidatat. Anim laborum proident consequat est duis ea deserunt cupidatat exercitation ea qui dolor. Veniam nostrud aliqua pariatur ipsum. Nisi cupidatat eu ipsum ut consectetur irure sint laborum dolore nostrud dolore ipsum. Anim irure anim cillum mollit ex reprehenderit commodo. Adipisicing reprehenderit sit qui eiusmod dolore nostrud commodo proident minim ut ut deserunt ullamco.\r\n","registered":"2019-02-08T05:19:25 -08:00","latitude":12.029664,"longitude":164.711199,"tags":["exercitation","est","consequat","irure","laborum","cillum","irure"],"friends":[{"id":0,"name":"Murray Johns"},{"id":1,"name":"Crane Hutchinson"},{"id":2,"name":"Wynn Castro"}],"greeting":"Hello, Diane Harrington! You have 7 unread messages.","favoriteFruit":"apple"}]", "[{"_id":"667d1d827fb270ffd9678130","index":0,"guid":"cba8a7b5-89d8-46ec-a6b8-68c6ad014ee1","isActive":true,"balance":"$1,286.08","picture":"http://placehold.it/32x32","age":26,"eyeColor":"green","name":"Barrett Zimmerman","gender":"male","company":"ZYTRAX","email":"barrettzimmerman@zytrax.com","phone":"+1 (980) 433-2997","address":"347 Logan Street, Cascades, Colorado, 8222","about":"Excepteur laborum qui consectetur enim non id ex id. Id ut officia fugiat nulla non minim irure adipisicing magna do occaecat reprehenderit duis duis. Quis quis dolor adipisicing nostrud reprehenderit nulla duis Lorem in eu Lorem.\r\n","registered":"2018-05-30T01:12:48 -08:00","latitude":-12.380399,"longitude":29.630323,"tags":["esse","nulla","irure","est","voluptate","nisi","consequat"],"friends":[{"id":0,"name":"Guy Haynes"},{"id":1,"name":"Aguirre Waller"},{"id":2,"name":"Freeman Parsons"}],"greeting":"Hello, Barrett Zimmerman! You have 4 unread messages.","favoriteFruit":"banana"},{"_id":"667d1d820979330df1da0945","index":1,"guid":"52484521-7816-4501-b278-b0f93005fbba","isActive":false,"balance":"$3,163.35","picture":"http://placehold.it/32x32","age":31,"eyeColor":"blue","name":"Jenny Shannon","gender":"female","company":"EPLOSION","email":"jennyshannon@eplosion.com","phone":"+1 (959) 554-2872","address":"909 Brighton Avenue, Cochranville, Iowa, 7261","about":"Dolor ipsum laborum fugiat ipsum tempor minim excepteur dolore esse irure. Ut sunt esse minim consequat est irure amet veniam ullamco. Commodo sit est eiusmod adipisicing deserunt incididunt ad. Consectetur commodo ea id aliquip ipsum velit culpa adipisicing. Sint nostrud ullamco duis et dolor magna laborum nisi ut ad adipisicing ut id tempor. Anim laborum qui ea sunt enim.\r\n","registered":"2016-09-27T04:10:16 -08:00","latitude":-18.507749,"longitude":60.414486,"tags":["duis","veniam","tempor","cillum","anim","sunt","proident"],"friends":[{"id":0,"name":"Herminia Silva"},{"id":1,"name":"Terrie Mckinney"},{"id":2,"name":"Valentine Richardson"}],"greeting":"Hello, Jenny Shannon! You have 2 unread messages.","favoriteFruit":"apple"}]", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试"] +["aaaaa", "12345!@#$%^&*()_", "", "中文测试", "123", "abs ss 123", "[{"_id":"667d1d6d78d92a8df5349ae8","index":0,"guid":"5e2e76b2-b2d4-477a-8962-4c36e554c21d","isActive":false,"balance":"$1,228.18","picture":"http://placehold.it/32x32","age":22,"eyeColor":"green","name":"Diane Harrington","gender":"female","company":"SUPPORTAL","email":"dianeharrington@supportal.com","phone":"+1 (990) 563-2570","address":"866 Cheever Place, Caln, Tennessee, 992","about":"Nulla est velit adipisicing labore labore anim et aute culpa aliqua cupidatat. Anim laborum proident consequat est duis ea deserunt cupidatat exercitation ea qui dolor. Veniam nostrud aliqua pariatur ipsum. Nisi cupidatat eu ipsum ut consectetur irure sint laborum dolore nostrud dolore ipsum. Anim irure anim cillum mollit ex reprehenderit commodo. Adipisicing reprehenderit sit qui eiusmod dolore nostrud commodo proident minim ut ut deserunt ullamco.\r\n","registered":"2019-02-08T05:19:25 -08:00","latitude":12.029664,"longitude":164.711199,"tags":["exercitation","est","consequat","irure","laborum","cillum","irure"],"friends":[{"id":0,"name":"Murray Johns"},{"id":1,"name":"Crane Hutchinson"},{"id":2,"name":"Wynn Castro"}],"greeting":"Hello, Diane Harrington! You have 7 unread messages.","favoriteFruit":"apple"}]", "[{"_id":"667d1d827fb270ffd9678130","index":0,"guid":"cba8a7b5-89d8-46ec-a6b8-68c6ad014ee1","isActive":true,"balance":"$1,286.08","picture":"http://placehold.it/32x32","age":26,"eyeColor":"green","name":"Barrett Zimmerman","gender":"male","company":"ZYTRAX","email":"barrettzimmerman@zytrax.com","phone":"+1 (980) 433-2997","address":"347 Logan Street, Cascades, Colorado, 8222","about":"Excepteur laborum qui consectetur enim non id ex id. Id ut officia fugiat nulla non minim irure adipisicing magna do occaecat reprehenderit duis duis. Quis quis dolor adipisicing nostrud reprehenderit nulla duis Lorem in eu Lorem.\r\n","registered":"2018-05-30T01:12:48 -08:00","latitude":-12.380399,"longitude":29.630323,"tags":["esse","nulla","irure","est","voluptate","nisi","consequat"],"friends":[{"id":0,"name":"Guy Haynes"},{"id":1,"name":"Aguirre Waller"},{"id":2,"name":"Freeman Parsons"}],"greeting":"Hello, Barrett Zimmerman! You have 4 unread messages.","favoriteFruit":"banana"},{"_id":"667d1d820979330df1da0945","index":1,"guid":"52484521-7816-4501-b278-b0f93005fbba","isActive":false,"balance":"$3,163.35","picture":"http://placehold.it/32x32","age":31,"eyeColor":"blue","name":"Jenny Shannon","gender":"female","company":"EPLOSION","email":"jennyshannon@eplosion.com","phone":"+1 (959) 554-2872","address":"909 Brighton Avenue, Cochranville, Iowa, 7261","about":"Dolor ipsum laborum fugiat ipsum tempor minim excepteur dolore esse irure. Ut sunt esse minim consequat est irure amet veniam ullamco. Commodo sit est eiusmod adipisicing deserunt incididunt ad. Consectetur commodo ea id aliquip ipsum velit culpa adipisicing. Sint nostrud ullamco duis et dolor magna laborum nisi ut ad adipisicing ut id tempor. Anim laborum qui ea sunt enim.\r\n","registered":"2016-09-27T04:10:16 -08:00","latitude":-18.507749,"longitude":60.414486,"tags":["duis","veniam","tempor","cillum","anim","sunt","proident"],"friends":[{"id":0,"name":"Herminia Silva"},{"id":1,"name":"Terrie Mckinney"},{"id":2,"name":"Valentine Richardson"}],"greeting":"Hello, Jenny Shannon! You have 2 unread messages.","favoriteFruit":"apple"}]", "aaaaaaaxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试"] [] [] [] @@ -35671,7 +37647,7 @@ NaN [] [] --- !sql_array_remove_Varchar -- +-- !sql_array_remove_String -- \N \N \N @@ -35692,14 +37668,14 @@ NaN \N \N ["12345! @#$ %^ &*()_", "d\\d", "\\", "\\aacdefghijklm\nopq\rs\ uvwxyzABCDEFGHIJKLMNOPQRSTUVWXY", "", "REPEAT('1',20)", "中文测试", "123", "abs ss 123", "C:UsersUsernameDocumentsfile.txt", "/home/username/documents/file.txt", "test@example.com", "http://www.example.com", "https://www.example.com", "2023-04-30", "30/04/2023", "April 30, 2023", "Line 1: This is the first line of a multiline text.\nLine 2: This is the second line of a multiline text.\nLine 3: This is the third line of a multiline text.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl. Sed euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl.", "你好世界!こんにちは世界!안녕하세요 세계!", "SGVsbG8gV29ybGQh", "YW55IGNvbnRlbnQ=", "dGhpcyBpcyBhIHRlc3Q=", "Zm9vYmFy", "SGVsbG8gV29ybGQh!", "YW55IGNvbnRlbnQ==", "dGhpcyBpcyBhIHRlc3Q", "Zm9vYmFy==", "[{"_id":"667d1d6d78d92a8df5349ae8","index":0,"guid":"5e2e76b2-b2d4-477a-8962-4c36e554c21d","isActive":false,"balance":"$1,228.18","picture":"http://placehold.it/32x32","age":22,"eyeColor":"green","name":"Diane Harrington","gender":"female","company":"SUPPORTAL","email":"dianeharrington@supportal.com","phone":"+1 (990) 563-2570","address":"866 Cheever Place, Caln, Tennessee, 992","about":"Nulla est velit adipisicing labore labore anim et aute culpa aliqua cupidatat. Anim laborum proident consequat est duis ea deserunt cupidatat exercitation ea qui dolor. Veniam nostrud aliqua pariatur ipsum. Nisi cupidatat eu ipsum ut consectetur irure sint laborum dolore nostrud dolore ipsum. Anim irure anim cillum mollit ex reprehenderit commodo. Adipisicing reprehenderit sit qui eiusmod dolore nostrud commodo proident minim ut ut deserunt ullamco.\r\n","registered":"2019-02-08T05:19:25 -08:00","latitude":12.029664,"longitude":164.711199,"tags":["exercitation","est","consequat","irure","laborum","cillum","irure"],"friends":[{"id":0,"name":"Murray Johns"},{"id":1,"name":"Crane Hutchinson"},{"id":2,"name":"Wynn Castro"}],"greeting":"Hello, Diane Harrington! You have 7 unread messages.","favoriteFruit":"apple"}]", "[{"_id":"667d1d827fb270ffd9678130","index":0,"guid":"cba8a7b5-89d8-46ec-a6b8-68c6ad014ee1","isActive":true,"balance":"$1,286.08","picture":"http://placehold.it/32x32","age":26,"eyeColor":"green","name":"Barrett Zimmerman","gender":"male","company":"ZYTRAX","email":"barrettzimmerman@zytrax.com","phone":"+1 (980) 433-2997","address":"347 Logan Street, Cascades, Colorado, 8222","about":"Excepteur laborum qui consectetur enim non id ex id. Id ut officia fugiat nulla non minim irure adipisicing magna do occaecat reprehenderit duis duis. Quis quis dolor adipisicing nostrud reprehenderit nulla duis Lorem in eu Lorem.\r\n","registered":"2018-05-30T01:12:48 -08:00","latitude":-12.380399,"longitude":29.630323,"tags":["esse","nulla","irure","est","voluptate","nisi","consequat"],"friends":[{"id":0,"name":"Guy Haynes"},{"id":1,"name":"Aguirre Waller"},{"id":2,"name":"Freeman Parsons"}],"greeting":"Hello, Barrett Zimmerman! You have 4 unread messages.","favoriteFruit":"banana"},{"_id":"667d1d820979330df1da0945","index":1,"guid":"52484521-7816-4501-b278-b0f93005fbba","isActive":false,"balance":"$3,163.35","picture":"http://placehold.it/32x32","age":31,"eyeColor":"blue","name":"Jenny Shannon","gender":"female","company":"EPLOSION","email":"jennyshannon@eplosion.com","phone":"+1 (959) 554-2872","address":"909 Brighton Avenue, Cochranville, Iowa, 7261","about":"Dolor ipsum laborum fugiat ipsum tempor minim excepteur dolore esse irure. Ut sunt esse minim consequat est irure amet veniam ullamco. Commodo sit est eiusmod adipisicing deserunt incididunt ad. Consectetur commodo ea id aliquip ipsum velit culpa adipisicing. Sint nostrud ullamco duis et dolor magna laborum nisi ut ad adipisicing ut id tempor. Anim laborum qui ea sunt enim.\r\n","registered":"2016-09-27T04:10:16 -08:00","latitude":-18.507749,"longitude":60.414486,"tags":["duis","veniam","tempor","cillum","anim","sunt","proident"],"friends":[{"id":0,"name":"Herminia Silva"},{"id":1,"name":"Terrie Mckinney"},{"id":2,"name":"Valentine Richardson"}],"greeting":"Hello, Jenny Shannon! You have 2 unread messages.","favoriteFruit":"apple"}]", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试"] -["aaaaa", "12345!@#$%^&*()_", "", "中文测试", "123", "abs ss 123", "[{"_id":"667d1d6d78d92a8df5349ae8","index":0,"guid":"5e2e76b2-b2d4-477a-8962-4c36e554c21d","isActive":false,"balance":"$1,228.18","picture":"http://placehold.it/32x32","age":22,"eyeColor":"green","name":"Diane Harrington","gender":"female","company":"SUPPORTAL","email":"dianeharrington@supportal.com","phone":"+1 (990) 563-2570","address":"866 Cheever Place, Caln, Tennessee, 992","about":"Nulla est velit adipisicing labore labore anim et aute culpa aliqua cupidatat. Anim laborum proident consequat est duis ea deserunt cupidatat exercitation ea qui dolor. Veniam nostrud aliqua pariatur ipsum. Nisi cupidatat eu ipsum ut consectetur irure sint laborum dolore nostrud dolore ipsum. Anim irure anim cillum mollit ex reprehenderit commodo. Adipisicing reprehenderit sit qui eiusmod dolore nostrud commodo proident minim ut ut deserunt ullamco.\r\n","registered":"2019-02-08T05:19:25 -08:00","latitude":12.029664,"longitude":164.711199,"tags":["exercitation","est","consequat","irure","laborum","cillum","irure"],"friends":[{"id":0,"name":"Murray Johns"},{"id":1,"name":"Crane Hutchinson"},{"id":2,"name":"Wynn Castro"}],"greeting":"Hello, Diane Harrington! You have 7 unread messages.","favoriteFruit":"apple"}]", "[{"_id":"667d1d827fb270ffd9678130","index":0,"guid":"cba8a7b5-89d8-46ec-a6b8-68c6ad014ee1","isActive":true,"balance":"$1,286.08","picture":"http://placehold.it/32x32","age":26,"eyeColor":"green","name":"Barrett Zimmerman","gender":"male","company":"ZYTRAX","email":"barrettzimmerman@zytrax.com","phone":"+1 (980) 433-2997","address":"347 Logan Street, Cascades, Colorado, 8222","about":"Excepteur laborum qui consectetur enim non id ex id. Id ut officia fugiat nulla non minim irure adipisicing magna do occaecat reprehenderit duis duis. Quis quis dolor adipisicing nostrud reprehenderit nulla duis Lorem in eu Lorem.\r\n","registered":"2018-05-30T01:12:48 -08:00","latitude":-12.380399,"longitude":29.630323,"tags":["esse","nulla","irure","est","voluptate","nisi","consequat"],"friends":[{"id":0,"name":"Guy Haynes"},{"id":1,"name":"Aguirre Waller"},{"id":2,"name":"Freeman Parsons"}],"greeting":"Hello, Barrett Zimmerman! You have 4 unread messages.","favoriteFruit":"banana"},{"_id":"667d1d820979330df1da0945","index":1,"guid":"52484521-7816-4501-b278-b0f93005fbba","isActive":false,"balance":"$3,163.35","picture":"http://placehold.it/32x32","age":31,"eyeColor":"blue","name":"Jenny Shannon","gender":"female","company":"EPLOSION","email":"jennyshannon@eplosion.com","phone":"+1 (959) 554-2872","address":"909 Brighton Avenue, Cochranville, Iowa, 7261","about":"Dolor ipsum laborum fugiat ipsum tempor minim excepteur dolore esse irure. Ut sunt esse minim consequat est irure amet veniam ullamco. Commodo sit est eiusmod adipisicing deserunt incididunt ad. Consectetur commodo ea id aliquip ipsum velit culpa adipisicing. Sint nostrud ullamco duis et dolor magna laborum nisi ut ad adipisicing ut id tempor. Anim laborum qui ea sunt enim.\r\n","registered":"2016-09-27T04:10:16 -08:00","latitude":-18.507749,"longitude":60.414486,"tags":["duis","veniam","tempor","cillum","anim","sunt","proident"],"friends":[{"id":0,"name":"Herminia Silva"},{"id":1,"name":"Terrie Mckinney"},{"id":2,"name":"Valentine Richardson"}],"greeting":"Hello, Jenny Shannon! You have 2 unread messages.","favoriteFruit":"apple"}]", "aaaaaaaxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试"] +["aaaaa", "12345!@#$%^&*()_", "", "中文测试", "123", "abs ss 123", "[{"_id":"667d1d6d78d92a8df5349ae8","index":0,"guid":"5e2e76b2-b2d4-477a-8962-4c36e554c21d","isActive":false,"balance":"$1,228.18","picture":"http://placehold.it/32x32","age":22,"eyeColor":"green","name":"Diane Harrington","gender":"female","company":"SUPPORTAL","email":"dianeharrington@supportal.com","phone":"+1 (990) 563-2570","address":"866 Cheever Place, Caln, Tennessee, 992","about":"Nulla est velit adipisicing labore labore anim et aute culpa aliqua cupidatat. Anim laborum proident consequat est duis ea deserunt cupidatat exercitation ea qui dolor. Veniam nostrud aliqua pariatur ipsum. Nisi cupidatat eu ipsum ut consectetur irure sint laborum dolore nostrud dolore ipsum. Anim irure anim cillum mollit ex reprehenderit commodo. Adipisicing reprehenderit sit qui eiusmod dolore nostrud commodo proident minim ut ut deserunt ullamco.\r\n","registered":"2019-02-08T05:19:25 -08:00","latitude":12.029664,"longitude":164.711199,"tags":["exercitation","est","consequat","irure","laborum","cillum","irure"],"friends":[{"id":0,"name":"Murray Johns"},{"id":1,"name":"Crane Hutchinson"},{"id":2,"name":"Wynn Castro"}],"greeting":"Hello, Diane Harrington! You have 7 unread messages.","favoriteFruit":"apple"}]", "[{"_id":"667d1d827fb270ffd9678130","index":0,"guid":"cba8a7b5-89d8-46ec-a6b8-68c6ad014ee1","isActive":true,"balance":"$1,286.08","picture":"http://placehold.it/32x32","age":26,"eyeColor":"green","name":"Barrett Zimmerman","gender":"male","company":"ZYTRAX","email":"barrettzimmerman@zytrax.com","phone":"+1 (980) 433-2997","address":"347 Logan Street, Cascades, Colorado, 8222","about":"Excepteur laborum qui consectetur enim non id ex id. Id ut officia fugiat nulla non minim irure adipisicing magna do occaecat reprehenderit duis duis. Quis quis dolor adipisicing nostrud reprehenderit nulla duis Lorem in eu Lorem.\r\n","registered":"2018-05-30T01:12:48 -08:00","latitude":-12.380399,"longitude":29.630323,"tags":["esse","nulla","irure","est","voluptate","nisi","consequat"],"friends":[{"id":0,"name":"Guy Haynes"},{"id":1,"name":"Aguirre Waller"},{"id":2,"name":"Freeman Parsons"}],"greeting":"Hello, Barrett Zimmerman! You have 4 unread messages.","favoriteFruit":"banana"},{"_id":"667d1d820979330df1da0945","index":1,"guid":"52484521-7816-4501-b278-b0f93005fbba","isActive":false,"balance":"$3,163.35","picture":"http://placehold.it/32x32","age":31,"eyeColor":"blue","name":"Jenny Shannon","gender":"female","company":"EPLOSION","email":"jennyshannon@eplosion.com","phone":"+1 (959) 554-2872","address":"909 Brighton Avenue, Cochranville, Iowa, 7261","about":"Dolor ipsum laborum fugiat ipsum tempor minim excepteur dolore esse irure. Ut sunt esse minim consequat est irure amet veniam ullamco. Commodo sit est eiusmod adipisicing deserunt incididunt ad. Consectetur commodo ea id aliquip ipsum velit culpa adipisicing. Sint nostrud ullamco duis et dolor magna laborum nisi ut ad adipisicing ut id tempor. Anim laborum qui ea sunt enim.\r\n","registered":"2016-09-27T04:10:16 -08:00","latitude":-18.507749,"longitude":60.414486,"tags":["duis","veniam","tempor","cillum","anim","sunt","proident"],"friends":[{"id":0,"name":"Herminia Silva"},{"id":1,"name":"Terrie Mckinney"},{"id":2,"name":"Valentine Richardson"}],"greeting":"Hello, Jenny Shannon! You have 2 unread messages.","favoriteFruit":"apple"}]", "aaaaaaaxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试"] [] [] [] --- !sql_array_remove_Varchar_notnull -- +-- !sql_array_remove_String_notnull -- ["12345! @#$ %^ &*()_", "d\\d", "\\", "\\aacdefghijklm\nopq\rs\ uvwxyzABCDEFGHIJKLMNOPQRSTUVWXY", "", "REPEAT('1',20)", "中文测试", "123", "abs ss 123", "C:UsersUsernameDocumentsfile.txt", "/home/username/documents/file.txt", "test@example.com", "http://www.example.com", "https://www.example.com", "2023-04-30", "30/04/2023", "April 30, 2023", "Line 1: This is the first line of a multiline text.\nLine 2: This is the second line of a multiline text.\nLine 3: This is the third line of a multiline text.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl. Sed euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl.", "你好世界!こんにちは世界!안녕하세요 세계!", "SGVsbG8gV29ybGQh", "YW55IGNvbnRlbnQ=", "dGhpcyBpcyBhIHRlc3Q=", "Zm9vYmFy", "SGVsbG8gV29ybGQh!", "YW55IGNvbnRlbnQ==", "dGhpcyBpcyBhIHRlc3Q", "Zm9vYmFy==", "[{"_id":"667d1d6d78d92a8df5349ae8","index":0,"guid":"5e2e76b2-b2d4-477a-8962-4c36e554c21d","isActive":false,"balance":"$1,228.18","picture":"http://placehold.it/32x32","age":22,"eyeColor":"green","name":"Diane Harrington","gender":"female","company":"SUPPORTAL","email":"dianeharrington@supportal.com","phone":"+1 (990) 563-2570","address":"866 Cheever Place, Caln, Tennessee, 992","about":"Nulla est velit adipisicing labore labore anim et aute culpa aliqua cupidatat. Anim laborum proident consequat est duis ea deserunt cupidatat exercitation ea qui dolor. Veniam nostrud aliqua pariatur ipsum. Nisi cupidatat eu ipsum ut consectetur irure sint laborum dolore nostrud dolore ipsum. Anim irure anim cillum mollit ex reprehenderit commodo. Adipisicing reprehenderit sit qui eiusmod dolore nostrud commodo proident minim ut ut deserunt ullamco.\r\n","registered":"2019-02-08T05:19:25 -08:00","latitude":12.029664,"longitude":164.711199,"tags":["exercitation","est","consequat","irure","laborum","cillum","irure"],"friends":[{"id":0,"name":"Murray Johns"},{"id":1,"name":"Crane Hutchinson"},{"id":2,"name":"Wynn Castro"}],"greeting":"Hello, Diane Harrington! You have 7 unread messages.","favoriteFruit":"apple"}]", "[{"_id":"667d1d827fb270ffd9678130","index":0,"guid":"cba8a7b5-89d8-46ec-a6b8-68c6ad014ee1","isActive":true,"balance":"$1,286.08","picture":"http://placehold.it/32x32","age":26,"eyeColor":"green","name":"Barrett Zimmerman","gender":"male","company":"ZYTRAX","email":"barrettzimmerman@zytrax.com","phone":"+1 (980) 433-2997","address":"347 Logan Street, Cascades, Colorado, 8222","about":"Excepteur laborum qui consectetur enim non id ex id. Id ut officia fugiat nulla non minim irure adipisicing magna do occaecat reprehenderit duis duis. Quis quis dolor adipisicing nostrud reprehenderit nulla duis Lorem in eu Lorem.\r\n","registered":"2018-05-30T01:12:48 -08:00","latitude":-12.380399,"longitude":29.630323,"tags":["esse","nulla","irure","est","voluptate","nisi","consequat"],"friends":[{"id":0,"name":"Guy Haynes"},{"id":1,"name":"Aguirre Waller"},{"id":2,"name":"Freeman Parsons"}],"greeting":"Hello, Barrett Zimmerman! You have 4 unread messages.","favoriteFruit":"banana"},{"_id":"667d1d820979330df1da0945","index":1,"guid":"52484521-7816-4501-b278-b0f93005fbba","isActive":false,"balance":"$3,163.35","picture":"http://placehold.it/32x32","age":31,"eyeColor":"blue","name":"Jenny Shannon","gender":"female","company":"EPLOSION","email":"jennyshannon@eplosion.com","phone":"+1 (959) 554-2872","address":"909 Brighton Avenue, Cochranville, Iowa, 7261","about":"Dolor ipsum laborum fugiat ipsum tempor minim excepteur dolore esse irure. Ut sunt esse minim consequat est irure amet veniam ullamco. Commodo sit est eiusmod adipisicing deserunt incididunt ad. Consectetur commodo ea id aliquip ipsum velit culpa adipisicing. Sint nostrud ullamco duis et dolor magna laborum nisi ut ad adipisicing ut id tempor. Anim laborum qui ea sunt enim.\r\n","registered":"2016-09-27T04:10:16 -08:00","latitude":-18.507749,"longitude":60.414486,"tags":["duis","veniam","tempor","cillum","anim","sunt","proident"],"friends":[{"id":0,"name":"Herminia Silva"},{"id":1,"name":"Terrie Mckinney"},{"id":2,"name":"Valentine Richardson"}],"greeting":"Hello, Jenny Shannon! You have 2 unread messages.","favoriteFruit":"apple"}]", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试"] -["aaaaa", "12345!@#$%^&*()_", "", "中文测试", "123", "abs ss 123", "[{"_id":"667d1d6d78d92a8df5349ae8","index":0,"guid":"5e2e76b2-b2d4-477a-8962-4c36e554c21d","isActive":false,"balance":"$1,228.18","picture":"http://placehold.it/32x32","age":22,"eyeColor":"green","name":"Diane Harrington","gender":"female","company":"SUPPORTAL","email":"dianeharrington@supportal.com","phone":"+1 (990) 563-2570","address":"866 Cheever Place, Caln, Tennessee, 992","about":"Nulla est velit adipisicing labore labore anim et aute culpa aliqua cupidatat. Anim laborum proident consequat est duis ea deserunt cupidatat exercitation ea qui dolor. Veniam nostrud aliqua pariatur ipsum. Nisi cupidatat eu ipsum ut consectetur irure sint laborum dolore nostrud dolore ipsum. Anim irure anim cillum mollit ex reprehenderit commodo. Adipisicing reprehenderit sit qui eiusmod dolore nostrud commodo proident minim ut ut deserunt ullamco.\r\n","registered":"2019-02-08T05:19:25 -08:00","latitude":12.029664,"longitude":164.711199,"tags":["exercitation","est","consequat","irure","laborum","cillum","irure"],"friends":[{"id":0,"name":"Murray Johns"},{"id":1,"name":"Crane Hutchinson"},{"id":2,"name":"Wynn Castro"}],"greeting":"Hello, Diane Harrington! You have 7 unread messages.","favoriteFruit":"apple"}]", "[{"_id":"667d1d827fb270ffd9678130","index":0,"guid":"cba8a7b5-89d8-46ec-a6b8-68c6ad014ee1","isActive":true,"balance":"$1,286.08","picture":"http://placehold.it/32x32","age":26,"eyeColor":"green","name":"Barrett Zimmerman","gender":"male","company":"ZYTRAX","email":"barrettzimmerman@zytrax.com","phone":"+1 (980) 433-2997","address":"347 Logan Street, Cascades, Colorado, 8222","about":"Excepteur laborum qui consectetur enim non id ex id. Id ut officia fugiat nulla non minim irure adipisicing magna do occaecat reprehenderit duis duis. Quis quis dolor adipisicing nostrud reprehenderit nulla duis Lorem in eu Lorem.\r\n","registered":"2018-05-30T01:12:48 -08:00","latitude":-12.380399,"longitude":29.630323,"tags":["esse","nulla","irure","est","voluptate","nisi","consequat"],"friends":[{"id":0,"name":"Guy Haynes"},{"id":1,"name":"Aguirre Waller"},{"id":2,"name":"Freeman Parsons"}],"greeting":"Hello, Barrett Zimmerman! You have 4 unread messages.","favoriteFruit":"banana"},{"_id":"667d1d820979330df1da0945","index":1,"guid":"52484521-7816-4501-b278-b0f93005fbba","isActive":false,"balance":"$3,163.35","picture":"http://placehold.it/32x32","age":31,"eyeColor":"blue","name":"Jenny Shannon","gender":"female","company":"EPLOSION","email":"jennyshannon@eplosion.com","phone":"+1 (959) 554-2872","address":"909 Brighton Avenue, Cochranville, Iowa, 7261","about":"Dolor ipsum laborum fugiat ipsum tempor minim excepteur dolore esse irure. Ut sunt esse minim consequat est irure amet veniam ullamco. Commodo sit est eiusmod adipisicing deserunt incididunt ad. Consectetur commodo ea id aliquip ipsum velit culpa adipisicing. Sint nostrud ullamco duis et dolor magna laborum nisi ut ad adipisicing ut id tempor. Anim laborum qui ea sunt enim.\r\n","registered":"2016-09-27T04:10:16 -08:00","latitude":-18.507749,"longitude":60.414486,"tags":["duis","veniam","tempor","cillum","anim","sunt","proident"],"friends":[{"id":0,"name":"Herminia Silva"},{"id":1,"name":"Terrie Mckinney"},{"id":2,"name":"Valentine Richardson"}],"greeting":"Hello, Jenny Shannon! You have 2 unread messages.","favoriteFruit":"apple"}]", "aaaaaaaxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试"] +["aaaaa", "12345!@#$%^&*()_", "", "中文测试", "123", "abs ss 123", "[{"_id":"667d1d6d78d92a8df5349ae8","index":0,"guid":"5e2e76b2-b2d4-477a-8962-4c36e554c21d","isActive":false,"balance":"$1,228.18","picture":"http://placehold.it/32x32","age":22,"eyeColor":"green","name":"Diane Harrington","gender":"female","company":"SUPPORTAL","email":"dianeharrington@supportal.com","phone":"+1 (990) 563-2570","address":"866 Cheever Place, Caln, Tennessee, 992","about":"Nulla est velit adipisicing labore labore anim et aute culpa aliqua cupidatat. Anim laborum proident consequat est duis ea deserunt cupidatat exercitation ea qui dolor. Veniam nostrud aliqua pariatur ipsum. Nisi cupidatat eu ipsum ut consectetur irure sint laborum dolore nostrud dolore ipsum. Anim irure anim cillum mollit ex reprehenderit commodo. Adipisicing reprehenderit sit qui eiusmod dolore nostrud commodo proident minim ut ut deserunt ullamco.\r\n","registered":"2019-02-08T05:19:25 -08:00","latitude":12.029664,"longitude":164.711199,"tags":["exercitation","est","consequat","irure","laborum","cillum","irure"],"friends":[{"id":0,"name":"Murray Johns"},{"id":1,"name":"Crane Hutchinson"},{"id":2,"name":"Wynn Castro"}],"greeting":"Hello, Diane Harrington! You have 7 unread messages.","favoriteFruit":"apple"}]", "[{"_id":"667d1d827fb270ffd9678130","index":0,"guid":"cba8a7b5-89d8-46ec-a6b8-68c6ad014ee1","isActive":true,"balance":"$1,286.08","picture":"http://placehold.it/32x32","age":26,"eyeColor":"green","name":"Barrett Zimmerman","gender":"male","company":"ZYTRAX","email":"barrettzimmerman@zytrax.com","phone":"+1 (980) 433-2997","address":"347 Logan Street, Cascades, Colorado, 8222","about":"Excepteur laborum qui consectetur enim non id ex id. Id ut officia fugiat nulla non minim irure adipisicing magna do occaecat reprehenderit duis duis. Quis quis dolor adipisicing nostrud reprehenderit nulla duis Lorem in eu Lorem.\r\n","registered":"2018-05-30T01:12:48 -08:00","latitude":-12.380399,"longitude":29.630323,"tags":["esse","nulla","irure","est","voluptate","nisi","consequat"],"friends":[{"id":0,"name":"Guy Haynes"},{"id":1,"name":"Aguirre Waller"},{"id":2,"name":"Freeman Parsons"}],"greeting":"Hello, Barrett Zimmerman! You have 4 unread messages.","favoriteFruit":"banana"},{"_id":"667d1d820979330df1da0945","index":1,"guid":"52484521-7816-4501-b278-b0f93005fbba","isActive":false,"balance":"$3,163.35","picture":"http://placehold.it/32x32","age":31,"eyeColor":"blue","name":"Jenny Shannon","gender":"female","company":"EPLOSION","email":"jennyshannon@eplosion.com","phone":"+1 (959) 554-2872","address":"909 Brighton Avenue, Cochranville, Iowa, 7261","about":"Dolor ipsum laborum fugiat ipsum tempor minim excepteur dolore esse irure. Ut sunt esse minim consequat est irure amet veniam ullamco. Commodo sit est eiusmod adipisicing deserunt incididunt ad. Consectetur commodo ea id aliquip ipsum velit culpa adipisicing. Sint nostrud ullamco duis et dolor magna laborum nisi ut ad adipisicing ut id tempor. Anim laborum qui ea sunt enim.\r\n","registered":"2016-09-27T04:10:16 -08:00","latitude":-18.507749,"longitude":60.414486,"tags":["duis","veniam","tempor","cillum","anim","sunt","proident"],"friends":[{"id":0,"name":"Herminia Silva"},{"id":1,"name":"Terrie Mckinney"},{"id":2,"name":"Valentine Richardson"}],"greeting":"Hello, Jenny Shannon! You have 2 unread messages.","favoriteFruit":"apple"}]", "aaaaaaaxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试"] [] [] [] @@ -35723,18 +37699,7 @@ NaN [] [] --- !sql_array_remove_String -- -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N +-- !sql_array_remove_DatetimeV2 -- \N \N \N @@ -35743,15 +37708,12 @@ NaN \N \N \N -["12345! @#$ %^ &*()_", "d\\d", "\\", "\\aacdefghijklm\nopq\rs\ uvwxyzABCDEFGHIJKLMNOPQRSTUVWXY", "", "REPEAT('1',20)", "中文测试", "123", "abs ss 123", "C:UsersUsernameDocumentsfile.txt", "/home/username/documents/file.txt", "test@example.com", "http://www.example.com", "https://www.example.com", "2023-04-30", "30/04/2023", "April 30, 2023", "Line 1: This is the first line of a multiline text.\nLine 2: This is the second line of a multiline text.\nLine 3: This is the third line of a multiline text.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl. Sed euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl.", "你好世界!こんにちは世界!안녕하세요 세계!", "SGVsbG8gV29ybGQh", "YW55IGNvbnRlbnQ=", "dGhpcyBpcyBhIHRlc3Q=", "Zm9vYmFy", "SGVsbG8gV29ybGQh!", "YW55IGNvbnRlbnQ==", "dGhpcyBpcyBhIHRlc3Q", "Zm9vYmFy==", "[{"_id":"667d1d6d78d92a8df5349ae8","index":0,"guid":"5e2e76b2-b2d4-477a-8962-4c36e554c21d","isActive":false,"balance":"$1,228.18","picture":"http://placehold.it/32x32","age":22,"eyeColor":"green","name":"Diane Harrington","gender":"female","company":"SUPPORTAL","email":"dianeharrington@supportal.com","phone":"+1 (990) 563-2570","address":"866 Cheever Place, Caln, Tennessee, 992","about":"Nulla est velit adipisicing labore labore anim et aute culpa aliqua cupidatat. Anim laborum proident consequat est duis ea deserunt cupidatat exercitation ea qui dolor. Veniam nostrud aliqua pariatur ipsum. Nisi cupidatat eu ipsum ut consectetur irure sint laborum dolore nostrud dolore ipsum. Anim irure anim cillum mollit ex reprehenderit commodo. Adipisicing reprehenderit sit qui eiusmod dolore nostrud commodo proident minim ut ut deserunt ullamco.\r\n","registered":"2019-02-08T05:19:25 -08:00","latitude":12.029664,"longitude":164.711199,"tags":["exercitation","est","consequat","irure","laborum","cillum","irure"],"friends":[{"id":0,"name":"Murray Johns"},{"id":1,"name":"Crane Hutchinson"},{"id":2,"name":"Wynn Castro"}],"greeting":"Hello, Diane Harrington! You have 7 unread messages.","favoriteFruit":"apple"}]", "[{"_id":"667d1d827fb270ffd9678130","index":0,"guid":"cba8a7b5-89d8-46ec-a6b8-68c6ad014ee1","isActive":true,"balance":"$1,286.08","picture":"http://placehold.it/32x32","age":26,"eyeColor":"green","name":"Barrett Zimmerman","gender":"male","company":"ZYTRAX","email":"barrettzimmerman@zytrax.com","phone":"+1 (980) 433-2997","address":"347 Logan Street, Cascades, Colorado, 8222","about":"Excepteur laborum qui consectetur enim non id ex id. Id ut officia fugiat nulla non minim irure adipisicing magna do occaecat reprehenderit duis duis. Quis quis dolor adipisicing nostrud reprehenderit nulla duis Lorem in eu Lorem.\r\n","registered":"2018-05-30T01:12:48 -08:00","latitude":-12.380399,"longitude":29.630323,"tags":["esse","nulla","irure","est","voluptate","nisi","consequat"],"friends":[{"id":0,"name":"Guy Haynes"},{"id":1,"name":"Aguirre Waller"},{"id":2,"name":"Freeman Parsons"}],"greeting":"Hello, Barrett Zimmerman! You have 4 unread messages.","favoriteFruit":"banana"},{"_id":"667d1d820979330df1da0945","index":1,"guid":"52484521-7816-4501-b278-b0f93005fbba","isActive":false,"balance":"$3,163.35","picture":"http://placehold.it/32x32","age":31,"eyeColor":"blue","name":"Jenny Shannon","gender":"female","company":"EPLOSION","email":"jennyshannon@eplosion.com","phone":"+1 (959) 554-2872","address":"909 Brighton Avenue, Cochranville, Iowa, 7261","about":"Dolor ipsum laborum fugiat ipsum tempor minim excepteur dolore esse irure. Ut sunt esse minim consequat est irure amet veniam ullamco. Commodo sit est eiusmod adipisicing deserunt incididunt ad. Consectetur commodo ea id aliquip ipsum velit culpa adipisicing. Sint nostrud ullamco duis et dolor magna laborum nisi ut ad adipisicing ut id tempor. Anim laborum qui ea sunt enim.\r\n","registered":"2016-09-27T04:10:16 -08:00","latitude":-18.507749,"longitude":60.414486,"tags":["duis","veniam","tempor","cillum","anim","sunt","proident"],"friends":[{"id":0,"name":"Herminia Silva"},{"id":1,"name":"Terrie Mckinney"},{"id":2,"name":"Valentine Richardson"}],"greeting":"Hello, Jenny Shannon! You have 2 unread messages.","favoriteFruit":"apple"}]", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试"] -["aaaaa", "12345!@#$%^&*()_", "", "中文测试", "123", "abs ss 123", "[{"_id":"667d1d6d78d92a8df5349ae8","index":0,"guid":"5e2e76b2-b2d4-477a-8962-4c36e554c21d","isActive":false,"balance":"$1,228.18","picture":"http://placehold.it/32x32","age":22,"eyeColor":"green","name":"Diane Harrington","gender":"female","company":"SUPPORTAL","email":"dianeharrington@supportal.com","phone":"+1 (990) 563-2570","address":"866 Cheever Place, Caln, Tennessee, 992","about":"Nulla est velit adipisicing labore labore anim et aute culpa aliqua cupidatat. Anim laborum proident consequat est duis ea deserunt cupidatat exercitation ea qui dolor. Veniam nostrud aliqua pariatur ipsum. Nisi cupidatat eu ipsum ut consectetur irure sint laborum dolore nostrud dolore ipsum. Anim irure anim cillum mollit ex reprehenderit commodo. Adipisicing reprehenderit sit qui eiusmod dolore nostrud commodo proident minim ut ut deserunt ullamco.\r\n","registered":"2019-02-08T05:19:25 -08:00","latitude":12.029664,"longitude":164.711199,"tags":["exercitation","est","consequat","irure","laborum","cillum","irure"],"friends":[{"id":0,"name":"Murray Johns"},{"id":1,"name":"Crane Hutchinson"},{"id":2,"name":"Wynn Castro"}],"greeting":"Hello, Diane Harrington! You have 7 unread messages.","favoriteFruit":"apple"}]", "[{"_id":"667d1d827fb270ffd9678130","index":0,"guid":"cba8a7b5-89d8-46ec-a6b8-68c6ad014ee1","isActive":true,"balance":"$1,286.08","picture":"http://placehold.it/32x32","age":26,"eyeColor":"green","name":"Barrett Zimmerman","gender":"male","company":"ZYTRAX","email":"barrettzimmerman@zytrax.com","phone":"+1 (980) 433-2997","address":"347 Logan Street, Cascades, Colorado, 8222","about":"Excepteur laborum qui consectetur enim non id ex id. Id ut officia fugiat nulla non minim irure adipisicing magna do occaecat reprehenderit duis duis. Quis quis dolor adipisicing nostrud reprehenderit nulla duis Lorem in eu Lorem.\r\n","registered":"2018-05-30T01:12:48 -08:00","latitude":-12.380399,"longitude":29.630323,"tags":["esse","nulla","irure","est","voluptate","nisi","consequat"],"friends":[{"id":0,"name":"Guy Haynes"},{"id":1,"name":"Aguirre Waller"},{"id":2,"name":"Freeman Parsons"}],"greeting":"Hello, Barrett Zimmerman! You have 4 unread messages.","favoriteFruit":"banana"},{"_id":"667d1d820979330df1da0945","index":1,"guid":"52484521-7816-4501-b278-b0f93005fbba","isActive":false,"balance":"$3,163.35","picture":"http://placehold.it/32x32","age":31,"eyeColor":"blue","name":"Jenny Shannon","gender":"female","company":"EPLOSION","email":"jennyshannon@eplosion.com","phone":"+1 (959) 554-2872","address":"909 Brighton Avenue, Cochranville, Iowa, 7261","about":"Dolor ipsum laborum fugiat ipsum tempor minim excepteur dolore esse irure. Ut sunt esse minim consequat est irure amet veniam ullamco. Commodo sit est eiusmod adipisicing deserunt incididunt ad. Consectetur commodo ea id aliquip ipsum velit culpa adipisicing. Sint nostrud ullamco duis et dolor magna laborum nisi ut ad adipisicing ut id tempor. Anim laborum qui ea sunt enim.\r\n","registered":"2016-09-27T04:10:16 -08:00","latitude":-18.507749,"longitude":60.414486,"tags":["duis","veniam","tempor","cillum","anim","sunt","proident"],"friends":[{"id":0,"name":"Herminia Silva"},{"id":1,"name":"Terrie Mckinney"},{"id":2,"name":"Valentine Richardson"}],"greeting":"Hello, Jenny Shannon! You have 2 unread messages.","favoriteFruit":"apple"}]", "aaaaaaaxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试"] +["0000-01-01 00:00:00.000000", "0000-01-02 00:00:00.000000", "0000-01-03 00:00:00.000000", "0000-01-04 00:00:00.000000", "0000-01-05 00:00:00.000000", "0000-01-06 00:00:00.000000", "0000-01-07 00:00:00.000000", "0000-12-31 00:00:00.000000", "0000-02-28 00:00:00.000000", "2020-02-28 00:00:00.000000", "2020-02-29 00:00:00.000000", "2020-03-01 00:00:00.000000", "2021-02-28 00:00:00.000000", "2021-03-01 00:00:00.000000", "1900-02-28 00:00:00.000000", "1900-03-01 00:00:00.000000", "9999-12-31 00:00:00.000000", "1969-12-31 00:00:00.000000", "1970-01-01 00:00:00.000000", null] +["0000-01-01 00:00:00.000000", "9999-12-31 00:00:00.000000", "2020-02-29 00:00:00.000000", "2021-02-28 00:00:00.000000", "0000-12-13 00:00:00.000000"] +["0000-01-01 00:00:00.000000", "9999-12-31 00:00:00.000000", "2020-02-29 00:00:00.000000", "2021-02-28 00:00:00.000000", null, null, null, "0000-12-13 00:00:00.000000", null, null] [] [] [] - --- !sql_array_remove_String_notnull -- -["12345! @#$ %^ &*()_", "d\\d", "\\", "\\aacdefghijklm\nopq\rs\ uvwxyzABCDEFGHIJKLMNOPQRSTUVWXY", "", "REPEAT('1',20)", "中文测试", "123", "abs ss 123", "C:UsersUsernameDocumentsfile.txt", "/home/username/documents/file.txt", "test@example.com", "http://www.example.com", "https://www.example.com", "2023-04-30", "30/04/2023", "April 30, 2023", "Line 1: This is the first line of a multiline text.\nLine 2: This is the second line of a multiline text.\nLine 3: This is the third line of a multiline text.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl. Sed euismod, nisl nec tincidunt lacinia, nunc nisl aliquam nunc, nec aliquam nisl nunc nec nisl.", "你好世界!こんにちは世界!안녕하세요 세계!", "SGVsbG8gV29ybGQh", "YW55IGNvbnRlbnQ=", "dGhpcyBpcyBhIHRlc3Q=", "Zm9vYmFy", "SGVsbG8gV29ybGQh!", "YW55IGNvbnRlbnQ==", "dGhpcyBpcyBhIHRlc3Q", "Zm9vYmFy==", "[{"_id":"667d1d6d78d92a8df5349ae8","index":0,"guid":"5e2e76b2-b2d4-477a-8962-4c36e554c21d","isActive":false,"balance":"$1,228.18","picture":"http://placehold.it/32x32","age":22,"eyeColor":"green","name":"Diane Harrington","gender":"female","company":"SUPPORTAL","email":"dianeharrington@supportal.com","phone":"+1 (990) 563-2570","address":"866 Cheever Place, Caln, Tennessee, 992","about":"Nulla est velit adipisicing labore labore anim et aute culpa aliqua cupidatat. Anim laborum proident consequat est duis ea deserunt cupidatat exercitation ea qui dolor. Veniam nostrud aliqua pariatur ipsum. Nisi cupidatat eu ipsum ut consectetur irure sint laborum dolore nostrud dolore ipsum. Anim irure anim cillum mollit ex reprehenderit commodo. Adipisicing reprehenderit sit qui eiusmod dolore nostrud commodo proident minim ut ut deserunt ullamco.\r\n","registered":"2019-02-08T05:19:25 -08:00","latitude":12.029664,"longitude":164.711199,"tags":["exercitation","est","consequat","irure","laborum","cillum","irure"],"friends":[{"id":0,"name":"Murray Johns"},{"id":1,"name":"Crane Hutchinson"},{"id":2,"name":"Wynn Castro"}],"greeting":"Hello, Diane Harrington! You have 7 unread messages.","favoriteFruit":"apple"}]", "[{"_id":"667d1d827fb270ffd9678130","index":0,"guid":"cba8a7b5-89d8-46ec-a6b8-68c6ad014ee1","isActive":true,"balance":"$1,286.08","picture":"http://placehold.it/32x32","age":26,"eyeColor":"green","name":"Barrett Zimmerman","gender":"male","company":"ZYTRAX","email":"barrettzimmerman@zytrax.com","phone":"+1 (980) 433-2997","address":"347 Logan Street, Cascades, Colorado, 8222","about":"Excepteur laborum qui consectetur enim non id ex id. Id ut officia fugiat nulla non minim irure adipisicing magna do occaecat reprehenderit duis duis. Quis quis dolor adipisicing nostrud reprehenderit nulla duis Lorem in eu Lorem.\r\n","registered":"2018-05-30T01:12:48 -08:00","latitude":-12.380399,"longitude":29.630323,"tags":["esse","nulla","irure","est","voluptate","nisi","consequat"],"friends":[{"id":0,"name":"Guy Haynes"},{"id":1,"name":"Aguirre Waller"},{"id":2,"name":"Freeman Parsons"}],"greeting":"Hello, Barrett Zimmerman! You have 4 unread messages.","favoriteFruit":"banana"},{"_id":"667d1d820979330df1da0945","index":1,"guid":"52484521-7816-4501-b278-b0f93005fbba","isActive":false,"balance":"$3,163.35","picture":"http://placehold.it/32x32","age":31,"eyeColor":"blue","name":"Jenny Shannon","gender":"female","company":"EPLOSION","email":"jennyshannon@eplosion.com","phone":"+1 (959) 554-2872","address":"909 Brighton Avenue, Cochranville, Iowa, 7261","about":"Dolor ipsum laborum fugiat ipsum tempor minim excepteur dolore esse irure. Ut sunt esse minim consequat est irure amet veniam ullamco. Commodo sit est eiusmod adipisicing deserunt incididunt ad. Consectetur commodo ea id aliquip ipsum velit culpa adipisicing. Sint nostrud ullamco duis et dolor magna laborum nisi ut ad adipisicing ut id tempor. Anim laborum qui ea sunt enim.\r\n","registered":"2016-09-27T04:10:16 -08:00","latitude":-18.507749,"longitude":60.414486,"tags":["duis","veniam","tempor","cillum","anim","sunt","proident"],"friends":[{"id":0,"name":"Herminia Silva"},{"id":1,"name":"Terrie Mckinney"},{"id":2,"name":"Valentine Richardson"}],"greeting":"Hello, Jenny Shannon! You have 2 unread messages.","favoriteFruit":"apple"}]", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试"] -["aaaaa", "12345!@#$%^&*()_", "", "中文测试", "123", "abs ss 123", "[{"_id":"667d1d6d78d92a8df5349ae8","index":0,"guid":"5e2e76b2-b2d4-477a-8962-4c36e554c21d","isActive":false,"balance":"$1,228.18","picture":"http://placehold.it/32x32","age":22,"eyeColor":"green","name":"Diane Harrington","gender":"female","company":"SUPPORTAL","email":"dianeharrington@supportal.com","phone":"+1 (990) 563-2570","address":"866 Cheever Place, Caln, Tennessee, 992","about":"Nulla est velit adipisicing labore labore anim et aute culpa aliqua cupidatat. Anim laborum proident consequat est duis ea deserunt cupidatat exercitation ea qui dolor. Veniam nostrud aliqua pariatur ipsum. Nisi cupidatat eu ipsum ut consectetur irure sint laborum dolore nostrud dolore ipsum. Anim irure anim cillum mollit ex reprehenderit commodo. Adipisicing reprehenderit sit qui eiusmod dolore nostrud commodo proident minim ut ut deserunt ullamco.\r\n","registered":"2019-02-08T05:19:25 -08:00","latitude":12.029664,"longitude":164.711199,"tags":["exercitation","est","consequat","irure","laborum","cillum","irure"],"friends":[{"id":0,"name":"Murray Johns"},{"id":1,"name":"Crane Hutchinson"},{"id":2,"name":"Wynn Castro"}],"greeting":"Hello, Diane Harrington! You have 7 unread messages.","favoriteFruit":"apple"}]", "[{"_id":"667d1d827fb270ffd9678130","index":0,"guid":"cba8a7b5-89d8-46ec-a6b8-68c6ad014ee1","isActive":true,"balance":"$1,286.08","picture":"http://placehold.it/32x32","age":26,"eyeColor":"green","name":"Barrett Zimmerman","gender":"male","company":"ZYTRAX","email":"barrettzimmerman@zytrax.com","phone":"+1 (980) 433-2997","address":"347 Logan Street, Cascades, Colorado, 8222","about":"Excepteur laborum qui consectetur enim non id ex id. Id ut officia fugiat nulla non minim irure adipisicing magna do occaecat reprehenderit duis duis. Quis quis dolor adipisicing nostrud reprehenderit nulla duis Lorem in eu Lorem.\r\n","registered":"2018-05-30T01:12:48 -08:00","latitude":-12.380399,"longitude":29.630323,"tags":["esse","nulla","irure","est","voluptate","nisi","consequat"],"friends":[{"id":0,"name":"Guy Haynes"},{"id":1,"name":"Aguirre Waller"},{"id":2,"name":"Freeman Parsons"}],"greeting":"Hello, Barrett Zimmerman! You have 4 unread messages.","favoriteFruit":"banana"},{"_id":"667d1d820979330df1da0945","index":1,"guid":"52484521-7816-4501-b278-b0f93005fbba","isActive":false,"balance":"$3,163.35","picture":"http://placehold.it/32x32","age":31,"eyeColor":"blue","name":"Jenny Shannon","gender":"female","company":"EPLOSION","email":"jennyshannon@eplosion.com","phone":"+1 (959) 554-2872","address":"909 Brighton Avenue, Cochranville, Iowa, 7261","about":"Dolor ipsum laborum fugiat ipsum tempor minim excepteur dolore esse irure. Ut sunt esse minim consequat est irure amet veniam ullamco. Commodo sit est eiusmod adipisicing deserunt incididunt ad. Consectetur commodo ea id aliquip ipsum velit culpa adipisicing. Sint nostrud ullamco duis et dolor magna laborum nisi ut ad adipisicing ut id tempor. Anim laborum qui ea sunt enim.\r\n","registered":"2016-09-27T04:10:16 -08:00","latitude":-18.507749,"longitude":60.414486,"tags":["duis","veniam","tempor","cillum","anim","sunt","proident"],"friends":[{"id":0,"name":"Herminia Silva"},{"id":1,"name":"Terrie Mckinney"},{"id":2,"name":"Valentine Richardson"}],"greeting":"Hello, Jenny Shannon! You have 2 unread messages.","favoriteFruit":"apple"}]", "aaaaaaaxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试"] [] [] [] @@ -35762,6 +37724,16 @@ NaN [] [] [] + +-- !sql_array_remove_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N [] [] [] @@ -35774,16 +37746,12 @@ NaN [] [] [] +[] +[null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null] +[null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +[null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] --- !sql_array_remove_DatetimeV2 -- -\N -\N -\N -\N -\N -\N -\N -\N +-- !sql_array_remove_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000", "0000-01-02 00:00:00.000000", "0000-01-03 00:00:00.000000", "0000-01-04 00:00:00.000000", "0000-01-05 00:00:00.000000", "0000-01-06 00:00:00.000000", "0000-01-07 00:00:00.000000", "0000-12-31 00:00:00.000000", "0000-02-28 00:00:00.000000", "2020-02-28 00:00:00.000000", "2020-02-29 00:00:00.000000", "2020-03-01 00:00:00.000000", "2021-02-28 00:00:00.000000", "2021-03-01 00:00:00.000000", "1900-02-28 00:00:00.000000", "1900-03-01 00:00:00.000000", "9999-12-31 00:00:00.000000", "1969-12-31 00:00:00.000000", "1970-01-01 00:00:00.000000", null] ["0000-01-01 00:00:00.000000", "9999-12-31 00:00:00.000000", "2020-02-29 00:00:00.000000", "2021-02-28 00:00:00.000000", "0000-12-13 00:00:00.000000"] ["0000-01-01 00:00:00.000000", "9999-12-31 00:00:00.000000", "2020-02-29 00:00:00.000000", "2021-02-28 00:00:00.000000", null, null, null, "0000-12-13 00:00:00.000000", null, null] @@ -35800,11 +37768,16 @@ NaN [] [] [] +[] +[] +[] +[] +[] +[] +[] +[] --- !sql_array_remove_DatetimeV2_notnull -- -["0000-01-01 00:00:00.000000", "0000-01-02 00:00:00.000000", "0000-01-03 00:00:00.000000", "0000-01-04 00:00:00.000000", "0000-01-05 00:00:00.000000", "0000-01-06 00:00:00.000000", "0000-01-07 00:00:00.000000", "0000-12-31 00:00:00.000000", "0000-02-28 00:00:00.000000", "2020-02-28 00:00:00.000000", "2020-02-29 00:00:00.000000", "2020-03-01 00:00:00.000000", "2021-02-28 00:00:00.000000", "2021-03-01 00:00:00.000000", "1900-02-28 00:00:00.000000", "1900-03-01 00:00:00.000000", "9999-12-31 00:00:00.000000", "1969-12-31 00:00:00.000000", "1970-01-01 00:00:00.000000", null] -["0000-01-01 00:00:00.000000", "9999-12-31 00:00:00.000000", "2020-02-29 00:00:00.000000", "2021-02-28 00:00:00.000000", "0000-12-13 00:00:00.000000"] -["0000-01-01 00:00:00.000000", "9999-12-31 00:00:00.000000", "2020-02-29 00:00:00.000000", "2021-02-28 00:00:00.000000", null, null, null, "0000-12-13 00:00:00.000000", null, null] +-- !sql_array_remove_TimestampNs_notnull -- [] [] [] @@ -35826,6 +37799,9 @@ NaN [] [] [] +[null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null, null, null, null, null, null] +[null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", null] +[null, null, null, null, null, null, null, null, null, "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", null, "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", null] -- !sql_array_remove_DateV2 -- \N @@ -36529,6 +38505,32 @@ NaN [null] [null] +-- !sql_array_reverse_sort_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", null, null, null, null, null, null, null, null] +["2021-12-31 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", null, null, null] +["2021-12-31 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-02-28 00:00:00.000000000", "1970-01-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", null, null, null, null, null, null, null, null, null, null, null] +["2021-12-31 00:00:00.000000000"] +[] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_reverse_sort_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000"] ["0000-12-13 00:00:00.000000"] @@ -36555,6 +38557,32 @@ NaN [null] [null] +-- !sql_array_reverse_sort_TimestampNs_notnull -- +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", null, null, null, null, null, null, null, null] +["2021-12-31 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", null, null, null] +["2021-12-31 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-02-28 00:00:00.000000000", "1970-01-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1900-02-28 00:00:00.000000000", null, null, null, null, null, null, null, null, null, null, null] +["2021-12-31 00:00:00.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_reverse_sort_DateV2 -- \N \N @@ -36685,7 +38713,137 @@ NaN [] [] --- !sql_array_slice_Float_notnull -- +-- !sql_array_slice_Float_notnull -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +[16] +[] +[] +[] +[] +[] + +-- !sql_array_slice_LargeInt -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +[16] +[] +[] +[] + +-- !sql_array_slice_LargeInt_notnull -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +[16] +[] +[] +[] +[] +[] + +-- !sql_array_slice_BigInt -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +[16] +[] +[] +[] +[] +[] + +-- !sql_array_slice_BigInt_notnull -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +[16] +[] +[] +[] +[] +[] + +-- !sql_array_slice_SmallInt -- \N \N \N @@ -36711,33 +38869,7 @@ NaN [] [] --- !sql_array_slice_LargeInt -- -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -[16] -[] -[] -[] - --- !sql_array_slice_LargeInt_notnull -- +-- !sql_array_slice_SmallInt_notnull -- \N \N \N @@ -36763,7 +38895,7 @@ NaN [] [] --- !sql_array_slice_BigInt -- +-- !sql_array_slice_Integer -- \N \N \N @@ -36789,7 +38921,7 @@ NaN [] [] --- !sql_array_slice_BigInt_notnull -- +-- !sql_array_slice_Integer_notnull -- \N \N \N @@ -36815,7 +38947,7 @@ NaN [] [] --- !sql_array_slice_SmallInt -- +-- !sql_array_slice_TinyInt -- \N \N \N @@ -36841,7 +38973,7 @@ NaN [] [] --- !sql_array_slice_SmallInt_notnull -- +-- !sql_array_slice_TinyInt_notnull -- \N \N \N @@ -36867,33 +38999,10 @@ NaN [] [] --- !sql_array_slice_Integer -- -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N +-- !sql_array_slice_DecimalV3 -- \N \N \N -[16] -[] -[] -[] -[] -[] - --- !sql_array_slice_Integer_notnull -- \N \N \N @@ -36912,14 +39021,11 @@ NaN \N \N \N -[16] -[] -[] [] [] [] --- !sql_array_slice_TinyInt -- +-- !sql_array_slice_DecimalV3_notnull -- \N \N \N @@ -36938,40 +39044,17 @@ NaN \N \N \N -[16] +[] [] [] [] [] [] --- !sql_array_slice_TinyInt_notnull -- -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N +-- !sql_array_slice_Boolean -- \N \N \N -[16] -[] -[] -[] -[] -[] - --- !sql_array_slice_DecimalV3 -- \N \N \N @@ -36993,11 +39076,8 @@ NaN \N \N \N -[] -[] -[] --- !sql_array_slice_DecimalV3_notnull -- +-- !sql_array_slice_Boolean_notnull -- \N \N \N @@ -37023,10 +39103,7 @@ NaN [] [] --- !sql_array_slice_Boolean -- -\N -\N -\N +-- !sql_array_slice_Char -- \N \N \N @@ -37048,8 +39125,11 @@ NaN \N \N \N +[] +[] +[] --- !sql_array_slice_Boolean_notnull -- +-- !sql_array_slice_Char_notnull -- \N \N \N @@ -37075,7 +39155,7 @@ NaN [] [] --- !sql_array_slice_Char -- +-- !sql_array_slice_Varchar -- \N \N \N @@ -37101,7 +39181,7 @@ NaN [] [] --- !sql_array_slice_Char_notnull -- +-- !sql_array_slice_Varchar_notnull -- \N \N \N @@ -37127,7 +39207,7 @@ NaN [] [] --- !sql_array_slice_Varchar -- +-- !sql_array_slice_String -- \N \N \N @@ -37153,7 +39233,7 @@ NaN [] [] --- !sql_array_slice_Varchar_notnull -- +-- !sql_array_slice_String_notnull -- \N \N \N @@ -37179,10 +39259,7 @@ NaN [] [] --- !sql_array_slice_String -- -\N -\N -\N +-- !sql_array_slice_DatetimeV2 -- \N \N \N @@ -37201,11 +39278,14 @@ NaN \N \N \N +["2021-02-28 00:00:00.000000"] +[] +[] [] [] [] --- !sql_array_slice_String_notnull -- +-- !sql_array_slice_TimestampNs -- \N \N \N @@ -37224,14 +39304,14 @@ NaN \N \N \N -[] +["2021-02-28 00:00:00.000000000"] [] [] [] [] [] --- !sql_array_slice_DatetimeV2 -- +-- !sql_array_slice_DatetimeV2_notnull -- \N \N \N @@ -37257,7 +39337,7 @@ NaN [] [] --- !sql_array_slice_DatetimeV2_notnull -- +-- !sql_array_slice_TimestampNs_notnull -- \N \N \N @@ -37276,7 +39356,7 @@ NaN \N \N \N -["2021-02-28 00:00:00.000000"] +["2021-02-28 00:00:00.000000000"] [] [] [] @@ -37985,6 +40065,32 @@ NaN [] [] +-- !sql_array_slice_three_params_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +[] +[] +[] +[] +[] +[] + -- !sql_array_slice_three_params_DatetimeV2_notnull -- \N \N @@ -38011,6 +40117,32 @@ NaN [] [] +-- !sql_array_slice_three_params_TimestampNs_notnull -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +[] +[] +[] +[] +[] +[] + -- !sql_array_slice_three_params_DateV2 -- \N \N @@ -38713,6 +40845,32 @@ NaN [null] [null] +-- !sql_array_sort_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000"] +[] +[null, null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, null, null, null, null, null, null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, null, null, null, null, null, null, null, null, null, null, "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_sort_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000", "0000-12-13 00:00:00.000000", "2020-02-29 00:00:00.000000", "2021-02-28 00:00:00.000000", "2021-12-31 00:00:00.000000", "9999-12-31 00:00:00.000000"] ["0000-01-01 00:00:00.000000"] @@ -38739,6 +40897,32 @@ NaN [null] [null] +-- !sql_array_sort_TimestampNs_notnull -- +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null, null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, null, null, null, null, null, null, null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, null, null, null, null, null, null, null, null, null, null, "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_sort_DateV2 -- \N \N @@ -39857,6 +42041,32 @@ NaN [null] [null] +-- !sql_array_union_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000"] +[] +[null, "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_union_DatetimeV2_notnull -- ["0000-01-01 00:00:00.000000", "0000-12-13 00:00:00.000000", "2020-02-29 00:00:00.000000", "2021-02-28 00:00:00.000000", "2021-12-31 00:00:00.000000", "9999-12-31 00:00:00.000000"] ["0000-01-01 00:00:00.000000"] @@ -39883,6 +42093,32 @@ NaN [null] [null] +-- !sql_array_union_TimestampNs_notnull -- +["2020-02-29 00:00:00.000000000"] +["2021-02-28 00:00:00.000000000"] +["2021-12-31 00:00:00.000000000"] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[null, "1900-02-28 00:00:00.000000000", "1900-03-01 00:00:00.000000000", "1969-12-31 00:00:00.000000000", "1970-01-01 00:00:00.000000000", "2020-02-28 00:00:00.000000000", "2020-02-29 00:00:00.000000000", "2020-03-01 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-03-01 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null, "2020-02-29 00:00:00.000000000", "2021-02-28 00:00:00.000000000", "2021-12-31 00:00:00.000000000"] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] +[null] + -- !sql_array_union_DateV2 -- \N \N @@ -40585,6 +42821,32 @@ NaN 21 6 +-- !sql_cardinality_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +11 +21 +6 + -- !sql_cardinality_DatetimeV2_notnull -- 0 0 @@ -40611,6 +42873,32 @@ NaN 21 6 +-- !sql_cardinality_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +11 +21 +6 + -- !sql_cardinality_DateV2 -- \N \N @@ -41050,10 +43338,218 @@ NaN 0 1 1 -12 -40 +12 +40 + +-- !sql_array_size_DecimalV3_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +12 +40 + +-- !sql_array_size_Boolean -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N + +-- !sql_array_size_Boolean_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + +-- !sql_array_size_Char -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +0 +1 +1 +33 +35 + +-- !sql_array_size_Char_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +33 +35 + +-- !sql_array_size_Varchar -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +0 +1 +1 +11 +33 + +-- !sql_array_size_Varchar_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +11 +33 + +-- !sql_array_size_String -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +0 +1 +1 +11 +33 --- !sql_array_size_DecimalV3_notnull -- +-- !sql_array_size_String_notnull -- 0 0 0 @@ -41076,73 +43572,10 @@ NaN 0 1 1 -12 -40 - --- !sql_array_size_Boolean -- -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N - --- !sql_array_size_Boolean_notnull -- -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 +11 +33 --- !sql_array_size_Char -- -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N +-- !sql_array_size_DatetimeV2 -- \N \N \N @@ -41154,99 +43587,21 @@ NaN 0 1 1 -33 -35 - --- !sql_array_size_Char_notnull -- -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 1 1 -33 -35 - --- !sql_array_size_Varchar -- -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -0 1 1 -11 -33 - --- !sql_array_size_Varchar_notnull -- -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 +1 +1 +1 +1 1 1 11 -33 +21 +6 --- !sql_array_size_String -- -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N -\N +-- !sql_array_size_TimestampNs -- \N \N \N @@ -41258,21 +43613,21 @@ NaN 0 1 1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 11 -33 +21 +6 --- !sql_array_size_String_notnull -- -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 +-- !sql_array_size_DatetimeV2_notnull -- 0 0 0 @@ -41284,21 +43639,6 @@ NaN 0 1 1 -11 -33 - --- !sql_array_size_DatetimeV2 -- -\N -\N -\N -\N -\N -\N -\N -\N -0 -1 -1 1 1 1 @@ -41313,7 +43653,7 @@ NaN 21 6 --- !sql_array_size_DatetimeV2_notnull -- +-- !sql_array_size_TimestampNs_notnull -- 0 0 0 @@ -42041,6 +44381,32 @@ NaN 21 6 +-- !sql_size_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +11 +21 +6 + -- !sql_size_DatetimeV2_notnull -- 0 0 @@ -42067,6 +44433,32 @@ NaN 21 6 +-- !sql_size_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +11 +21 +6 + -- !sql_size_DateV2 -- \N \N diff --git a/regression-test/data/nereids_function_p0/scalar_function/Array2.out b/regression-test/data/nereids_function_p0/scalar_function/Array2.out index 7767feb9c14032..c8d439a5f6757e 100644 --- a/regression-test/data/nereids_function_p0/scalar_function/Array2.out +++ b/regression-test/data/nereids_function_p0/scalar_function/Array2.out @@ -143,6 +143,12 @@ -- !sql_array_sort_DatetimeV2_notnull -- ["2012-03-12 12:11:12.000000", "2012-03-11 11:10:11.000000", "2012-03-10 10:09:10.000000", "2012-03-09 09:08:09.000000", "2012-03-08 08:07:08.000000", "2012-03-07 07:06:07.000000", "2012-03-06 06:05:06.000000", "2012-03-05 05:04:05.000000", "2012-03-04 04:03:04.000000", "2012-03-03 03:02:03.000000", "2012-03-02 02:01:02.000000", "2012-03-01 01:00:01.000000"] +-- !sql_array_sort_TimestampNs -- +[null, "2012-03-12 12:11:12.000000000", "2012-03-11 11:10:11.000000000", "2012-03-10 10:09:10.000000000", "2012-03-09 09:08:09.000000000", "2012-03-08 08:07:08.000000000", "2012-03-07 07:06:07.000000000", "2012-03-06 06:05:06.000000000", "2012-03-05 05:04:05.000000000", "2012-03-04 04:03:04.000000000", "2012-03-03 03:02:03.000000000", "2012-03-02 02:01:02.000000000", "2012-03-01 01:00:01.000000000"] + +-- !sql_array_sort_TimestampNs_notnull -- +["2012-03-12 12:11:12.000000000", "2012-03-11 11:10:11.000000000", "2012-03-10 10:09:10.000000000", "2012-03-09 09:08:09.000000000", "2012-03-08 08:07:08.000000000", "2012-03-07 07:06:07.000000000", "2012-03-06 06:05:06.000000000", "2012-03-05 05:04:05.000000000", "2012-03-04 04:03:04.000000000", "2012-03-03 03:02:03.000000000", "2012-03-02 02:01:02.000000000", "2012-03-01 01:00:01.000000000"] + -- !sql_array_sort_Boolean -- [null, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0] @@ -209,6 +215,11 @@ 2 [null, "2024-02-09 10:00:00.000000", "2024-02-08 10:00:00.000000", "2024-02-07 10:00:00.000000", "2024-02-06 10:00:00.000000"] 3 [null, "2024-03-04 10:00:00.000000", "2024-03-03 10:00:00.000000", "2024-03-02 10:00:00.000000", "2024-03-01 10:00:00.000000"] +-- !sql_array_sort_lambda_multir_timestamp_ns -- +1 [null, "2024-01-05 10:00:00.000000000", "2024-01-03 10:00:00.000000000", "2024-01-02 10:00:00.000000000", "2024-01-01 10:00:00.000000000"] +2 [null, "2024-02-09 10:00:00.000000000", "2024-02-08 10:00:00.000000000", "2024-02-07 10:00:00.000000000", "2024-02-06 10:00:00.000000000"] +3 [null, "2024-03-04 10:00:00.000000000", "2024-03-03 10:00:00.000000000", "2024-03-02 10:00:00.000000000", "2024-03-01 10:00:00.000000000"] + -- !sql_array_sort_lambda_multir_char -- 1 [null, "e", "c", "b", "a"] 2 [null, "i", "h", "g", "f"] diff --git a/regression-test/data/nereids_function_p0/scalar_function/C.out b/regression-test/data/nereids_function_p0/scalar_function/C.out index 924ddf5b148105..b854cb3af18dd1 100644 --- a/regression-test/data/nereids_function_p0/scalar_function/C.out +++ b/regression-test/data/nereids_function_p0/scalar_function/C.out @@ -594,6 +594,21 @@ true 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_coalesce_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_coalesce_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -608,6 +623,20 @@ true 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_coalesce_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_coalesce_DateV2 -- \N 2012-03-01 @@ -1058,6 +1087,21 @@ varchar13 2012-03-11T05:10:11 2012-03-12T06:11:12 +-- !sql_convert_tz_TimestampNs_Varchar_Varchar -- +\N +2012-02-29 19:00:01.000000000 +2012-03-01 20:01:02.000000000 +2012-03-02 21:02:03.000000000 +2012-03-03 22:03:04.000000000 +2012-03-04 23:04:05.000000000 +2012-03-06 00:05:06.000000000 +2012-03-07 01:06:07.000000000 +2012-03-08 02:07:08.000000000 +2012-03-09 03:08:09.000000000 +2012-03-10 04:09:10.000000000 +2012-03-11 05:10:11.000000000 +2012-03-12 06:11:12.000000000 + -- !sql_convert_tz_DateTimeV2_Varchar_Varchar_notnull -- 2012-02-29T19:00:01 2012-03-01T20:01:02 @@ -1072,6 +1116,20 @@ varchar13 2012-03-11T05:10:11 2012-03-12T06:11:12 +-- !sql_convert_tz_TimestampNs_Varchar_Varchar_notnull -- +2012-02-29 19:00:01.000000000 +2012-03-01 20:01:02.000000000 +2012-03-02 21:02:03.000000000 +2012-03-03 22:03:04.000000000 +2012-03-04 23:04:05.000000000 +2012-03-06 00:05:06.000000000 +2012-03-07 01:06:07.000000000 +2012-03-08 02:07:08.000000000 +2012-03-09 03:08:09.000000000 +2012-03-10 04:09:10.000000000 +2012-03-11 05:10:11.000000000 +2012-03-12 06:11:12.000000000 + -- !sql_cos_Double -- \N 0.9950041652780258 @@ -1379,9 +1437,15 @@ varchar13 -- !kadtmv2 -- 12 +-- !kadtmv2_timestamp_ns -- +12 + -- !kadtmv2_not_nullable -- 12 +-- !kadtmv2_not_nullable_timestamp_ns -- +12 + -- !kachr -- 12 diff --git a/regression-test/data/nereids_function_p0/scalar_function/D.out b/regression-test/data/nereids_function_p0/scalar_function/D.out index 6c1ee1b0f884eb..18ae4915e6f483 100644 --- a/regression-test/data/nereids_function_p0/scalar_function/D.out +++ b/regression-test/data/nereids_function_p0/scalar_function/D.out @@ -43,6 +43,21 @@ 2012-03-11 2012-03-12 +-- !sql_date_TimestampNs -- +\N +2012-03-01 +2012-03-02 +2012-03-03 +2012-03-04 +2012-03-05 +2012-03-06 +2012-03-07 +2012-03-08 +2012-03-09 +2012-03-10 +2012-03-11 +2012-03-12 + -- !sql_date_DateTimeV2_notnull -- 2012-03-01 2012-03-02 @@ -57,6 +72,20 @@ 2012-03-11 2012-03-12 +-- !sql_date_TimestampNs_notnull -- +2012-03-01 +2012-03-02 +2012-03-03 +2012-03-04 +2012-03-05 +2012-03-06 +2012-03-07 +2012-03-08 +2012-03-09 +2012-03-10 +2012-03-11 +2012-03-12 + -- !sql_date_format_DateTime_Varchar -- \N 2006-01-02 12:00:00 @@ -130,6 +159,21 @@ 2006-01-02 12:00:00 2006-01-02 12:00:00 +-- !sql_date_format_TimestampNs_Varchar -- +\N +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 + -- !sql_date_format_DateTimeV2_Varchar_notnull -- 2006-01-02 12:00:00 2006-01-02 12:00:00 @@ -144,6 +188,20 @@ 2006-01-02 12:00:00 2006-01-02 12:00:00 +-- !sql_date_format_TimestampNs_Varchar_notnull -- +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 +2006-01-02 12:00:00 + -- !sql_date_format_DateV2_Varchar -- \N 2006-01-02 @@ -217,6 +275,21 @@ 2012-03-11T00:00 2012-03-12T00:00 +-- !sql_date_trunc_TimestampNs_Varchar -- +\N +2012-03-01 00:00:00.000000000 +2012-03-02 00:00:00.000000000 +2012-03-03 00:00:00.000000000 +2012-03-04 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-06 00:00:00.000000000 +2012-03-07 00:00:00.000000000 +2012-03-08 00:00:00.000000000 +2012-03-09 00:00:00.000000000 +2012-03-10 00:00:00.000000000 +2012-03-11 00:00:00.000000000 +2012-03-12 00:00:00.000000000 + -- !sql_date_trunc_DateTimeV2_Varchar_notnull -- 2012-03-01T01:00 2012-03-02T02:00 @@ -231,6 +304,20 @@ 2012-03-11T11:00 2012-03-12T12:00 +-- !sql_date_trunc_TimestampNs_Varchar_notnull -- +2012-03-01 01:00:00.000000000 +2012-03-02 02:00:00.000000000 +2012-03-03 03:00:00.000000000 +2012-03-04 04:00:00.000000000 +2012-03-05 05:00:00.000000000 +2012-03-06 06:00:00.000000000 +2012-03-07 07:00:00.000000000 +2012-03-08 08:00:00.000000000 +2012-03-09 09:00:00.000000000 +2012-03-10 10:00:00.000000000 +2012-03-11 11:00:00.000000000 +2012-03-12 12:00:00.000000000 + -- !sql_date_trunc_Date_Varchar -- \N 2012-03-01 @@ -333,6 +420,21 @@ 0 0 +-- !sql_datediff_TimestampNs_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_datediff_DateTimeV2_DateTimeV2_notnull -- 0 0 @@ -347,6 +449,20 @@ 0 0 +-- !sql_datediff_TimestampNs_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_datediff_DateTimeV2_DateV2 -- \N 0 @@ -362,6 +478,21 @@ 0 0 +-- !sql_datediff_TimestampNs_DateV2 -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_datediff_DateTimeV2_DateV2_notnull -- 0 0 @@ -376,6 +507,20 @@ 0 0 +-- !sql_datediff_TimestampNs_DateV2_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_datediff_DateV2_DateTimeV2 -- \N 0 @@ -391,6 +536,21 @@ 0 0 +-- !sql_datediff_DateV2_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_datediff_DateV2_DateTimeV2_notnull -- 0 0 @@ -405,6 +565,20 @@ 0 0 +-- !sql_datediff_DateV2_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_datediff_DateV2_DateV2 -- \N 0 @@ -449,6 +623,21 @@ 0 0 +-- !sql_datediff_TimestampNs_DateTime -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_datediff_DateTimeV2_DateTime_notnull -- 0 0 @@ -463,6 +652,20 @@ 0 0 +-- !sql_datediff_TimestampNs_DateTime_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_datediff_DateV2_DateTime -- \N 0 @@ -519,6 +722,21 @@ 2012-03-11 2012-03-12 +-- !sql_datev2_TimestampNs -- +\N +2012-03-01 +2012-03-02 +2012-03-03 +2012-03-04 +2012-03-05 +2012-03-06 +2012-03-07 +2012-03-08 +2012-03-09 +2012-03-10 +2012-03-11 +2012-03-12 + -- !sql_datev2_DateTimeV2_notnull -- 2012-03-01 2012-03-02 @@ -533,6 +751,20 @@ 2012-03-11 2012-03-12 +-- !sql_datev2_TimestampNs_notnull -- +2012-03-01 +2012-03-02 +2012-03-03 +2012-03-04 +2012-03-05 +2012-03-06 +2012-03-07 +2012-03-08 +2012-03-09 +2012-03-10 +2012-03-11 +2012-03-12 + -- !sql_day_ceil_DateTime -- \N 2012-03-02T00:00 @@ -577,6 +809,21 @@ 2012-03-12T00:00 2012-03-13T00:00 +-- !sql_day_ceil_TimestampNs -- +\N +2012-03-02 00:00:00.000000000 +2012-03-03 00:00:00.000000000 +2012-03-04 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-06 00:00:00.000000000 +2012-03-07 00:00:00.000000000 +2012-03-08 00:00:00.000000000 +2012-03-09 00:00:00.000000000 +2012-03-10 00:00:00.000000000 +2012-03-11 00:00:00.000000000 +2012-03-12 00:00:00.000000000 +2012-03-13 00:00:00.000000000 + -- !sql_day_ceil_DateTimeV2_notnull -- 2012-03-02T00:00 2012-03-03T00:00 @@ -591,6 +838,20 @@ 2012-03-12T00:00 2012-03-13T00:00 +-- !sql_day_ceil_TimestampNs_notnull -- +2012-03-02 00:00:00.000000000 +2012-03-03 00:00:00.000000000 +2012-03-04 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-06 00:00:00.000000000 +2012-03-07 00:00:00.000000000 +2012-03-08 00:00:00.000000000 +2012-03-09 00:00:00.000000000 +2012-03-10 00:00:00.000000000 +2012-03-11 00:00:00.000000000 +2012-03-12 00:00:00.000000000 +2012-03-13 00:00:00.000000000 + -- !sql_day_ceil_DateV2 -- \N 2012-03-01 @@ -693,6 +954,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_day_ceil_TimestampNs_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_day_ceil_DateTimeV2_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -707,6 +983,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_day_ceil_TimestampNs_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_day_ceil_DateTimeV2_Integer -- \N 2012-03-02T00:00 @@ -722,6 +1012,21 @@ 2012-03-19T00:00 2012-03-19T00:00 +-- !sql_day_ceil_TimestampNs_Integer -- +\N +2012-03-02 00:00:00.000000000 +2012-03-03 00:00:00.000000000 +2012-03-04 00:00:00.000000000 +2012-03-07 00:00:00.000000000 +2012-03-09 00:00:00.000000000 +2012-03-07 00:00:00.000000000 +2012-03-12 00:00:00.000000000 +2012-03-15 00:00:00.000000000 +2012-03-10 00:00:00.000000000 +2012-03-19 00:00:00.000000000 +2012-03-19 00:00:00.000000000 +2012-03-19 00:00:00.000000000 + -- !sql_day_ceil_DateTimeV2_Integer_notnull -- 2012-03-02T00:00 2012-03-03T00:00 @@ -736,6 +1041,20 @@ 2012-03-19T00:00 2012-03-19T00:00 +-- !sql_day_ceil_TimestampNs_Integer_notnull -- +2012-03-02 00:00:00.000000000 +2012-03-03 00:00:00.000000000 +2012-03-04 00:00:00.000000000 +2012-03-07 00:00:00.000000000 +2012-03-09 00:00:00.000000000 +2012-03-07 00:00:00.000000000 +2012-03-12 00:00:00.000000000 +2012-03-15 00:00:00.000000000 +2012-03-10 00:00:00.000000000 +2012-03-19 00:00:00.000000000 +2012-03-19 00:00:00.000000000 +2012-03-19 00:00:00.000000000 + -- !sql_day_ceil_DateV2_DateV2 -- \N 2012-03-01 @@ -838,6 +1157,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_day_ceil_TimestampNs_Integer_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_day_ceil_DateTimeV2_Integer_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -852,6 +1186,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_day_ceil_TimestampNs_Integer_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_day_ceil_DateV2_Integer_DateV2 -- \N 2012-03-01 @@ -925,6 +1273,21 @@ 2012-03-11T00:00 2012-03-12T00:00 +-- !sql_day_floor_TimestampNs -- +\N +2012-03-01 00:00:00.000000000 +2012-03-02 00:00:00.000000000 +2012-03-03 00:00:00.000000000 +2012-03-04 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-06 00:00:00.000000000 +2012-03-07 00:00:00.000000000 +2012-03-08 00:00:00.000000000 +2012-03-09 00:00:00.000000000 +2012-03-10 00:00:00.000000000 +2012-03-11 00:00:00.000000000 +2012-03-12 00:00:00.000000000 + -- !sql_day_floor_DateTimeV2_notnull -- 2012-03-01T00:00 2012-03-02T00:00 @@ -939,6 +1302,20 @@ 2012-03-11T00:00 2012-03-12T00:00 +-- !sql_day_floor_TimestampNs_notnull -- +2012-03-01 00:00:00.000000000 +2012-03-02 00:00:00.000000000 +2012-03-03 00:00:00.000000000 +2012-03-04 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-06 00:00:00.000000000 +2012-03-07 00:00:00.000000000 +2012-03-08 00:00:00.000000000 +2012-03-09 00:00:00.000000000 +2012-03-10 00:00:00.000000000 +2012-03-11 00:00:00.000000000 +2012-03-12 00:00:00.000000000 + -- !sql_day_floor_DateV2 -- \N 2012-03-01 @@ -1041,6 +1418,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_day_floor_TimestampNs_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_day_floor_DateTimeV2_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -1055,6 +1447,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_day_floor_TimestampNs_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_day_floor_DateTimeV2_Integer -- \N 2012-03-01T00:00 @@ -1070,6 +1476,21 @@ 2012-03-08T00:00 2012-03-07T00:00 +-- !sql_day_floor_TimestampNs_Integer -- +\N +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-03 00:00:00.000000000 +2012-03-04 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-07 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-09 00:00:00.000000000 +2012-03-08 00:00:00.000000000 +2012-03-07 00:00:00.000000000 + -- !sql_day_floor_DateTimeV2_Integer_notnull -- 2012-03-01T00:00 2012-03-01T00:00 @@ -1084,6 +1505,20 @@ 2012-03-08T00:00 2012-03-07T00:00 +-- !sql_day_floor_TimestampNs_Integer_notnull -- +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-03 00:00:00.000000000 +2012-03-04 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-07 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-09 00:00:00.000000000 +2012-03-08 00:00:00.000000000 +2012-03-07 00:00:00.000000000 + -- !sql_day_floor_DateV2_DateV2 -- \N 2012-03-01 @@ -1186,6 +1621,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_day_floor_TimestampNs_Integer_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_day_floor_DateTimeV2_Integer_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -1200,6 +1650,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_day_floor_TimestampNs_Integer_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_day_floor_DateV2_Integer_DateV2 -- \N 2012-03-01 @@ -1273,6 +1737,21 @@ Saturday Sunday Monday +-- !sql_dayname_TimestampNs -- +\N +Thursday +Friday +Saturday +Sunday +Monday +Tuesday +Wednesday +Thursday +Friday +Saturday +Sunday +Monday + -- !sql_dayname_DateTimeV2_notnull -- Thursday Friday @@ -1287,6 +1766,20 @@ Saturday Sunday Monday +-- !sql_dayname_TimestampNs_notnull -- +Thursday +Friday +Saturday +Sunday +Monday +Tuesday +Wednesday +Thursday +Friday +Saturday +Sunday +Monday + -- !sql_dayname_DateV2 -- \N Thursday @@ -1360,6 +1853,21 @@ Monday 11 12 +-- !sql_dayofmonth_TimestampNs -- +\N +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 + -- !sql_dayofmonth_DateTimeV2_notnull -- 1 2 @@ -1374,6 +1882,20 @@ Monday 11 12 +-- !sql_dayofmonth_TimestampNs_notnull -- +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 + -- !sql_dayofmonth_DateV2 -- \N 1 @@ -1447,6 +1969,21 @@ Monday 1 2 +-- !sql_dayofweek_TimestampNs -- +\N +5 +6 +7 +1 +2 +3 +4 +5 +6 +7 +1 +2 + -- !sql_dayofweek_DateTimeV2_notnull -- 5 6 @@ -1461,6 +1998,20 @@ Monday 1 2 +-- !sql_dayofweek_TimestampNs_notnull -- +5 +6 +7 +1 +2 +3 +4 +5 +6 +7 +1 +2 + -- !sql_dayofweek_DateV2 -- \N 5 @@ -1534,6 +2085,21 @@ Monday 71 72 +-- !sql_dayofyear_TimestampNs -- +\N +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 + -- !sql_dayofyear_DateTimeV2_notnull -- 61 62 @@ -1548,6 +2114,20 @@ Monday 71 72 +-- !sql_dayofyear_TimestampNs_notnull -- +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 + -- !sql_dayofyear_DateV2 -- \N 61 @@ -1592,6 +2172,21 @@ Monday 2012-03-22T11:10:11 2012-03-24T12:11:12 +-- !sql_days_add_TimestampNs_Integer -- +\N +2012-03-02 01:00:01.000000000 +2012-03-04 02:01:02.000000000 +2012-03-06 03:02:03.000000000 +2012-03-08 04:03:04.000000000 +2012-03-10 05:04:05.000000000 +2012-03-12 06:05:06.000000000 +2012-03-14 07:06:07.000000000 +2012-03-16 08:07:08.000000000 +2012-03-18 09:08:09.000000000 +2012-03-20 10:09:10.000000000 +2012-03-22 11:10:11.000000000 +2012-03-24 12:11:12.000000000 + -- !sql_days_add_DateTimeV2_Integer_notnull -- 2012-03-02T01:00:01 2012-03-04T02:01:02 @@ -1606,6 +2201,20 @@ Monday 2012-03-22T11:10:11 2012-03-24T12:11:12 +-- !sql_days_add_TimestampNs_Integer_notnull -- +2012-03-02 01:00:01.000000000 +2012-03-04 02:01:02.000000000 +2012-03-06 03:02:03.000000000 +2012-03-08 04:03:04.000000000 +2012-03-10 05:04:05.000000000 +2012-03-12 06:05:06.000000000 +2012-03-14 07:06:07.000000000 +2012-03-16 08:07:08.000000000 +2012-03-18 09:08:09.000000000 +2012-03-20 10:09:10.000000000 +2012-03-22 11:10:11.000000000 +2012-03-24 12:11:12.000000000 + -- !sql_days_add_DateV2_Integer -- \N 2012-03-02 @@ -1853,6 +2462,21 @@ Monday 0 0 +-- !sql_days_diff_TimestampNs_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_days_diff_DateTimeV2_DateTimeV2_notnull -- 0 0 @@ -1867,6 +2491,20 @@ Monday 0 0 +-- !sql_days_diff_TimestampNs_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_days_diff_DateV2_DateTimeV2 -- \N 0 @@ -1882,6 +2520,21 @@ Monday 0 0 +-- !sql_days_diff_DateV2_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_days_diff_DateV2_DateTimeV2_notnull -- 0 0 @@ -1896,6 +2549,20 @@ Monday 0 0 +-- !sql_days_diff_DateV2_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_days_diff_DateTimeV2_DateV2 -- \N 0 @@ -1911,6 +2578,21 @@ Monday 0 0 +-- !sql_days_diff_TimestampNs_DateV2 -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_days_diff_DateTimeV2_DateV2_notnull -- 0 0 @@ -1925,6 +2607,20 @@ Monday 0 0 +-- !sql_days_diff_TimestampNs_DateV2_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_days_diff_DateV2_DateV2 -- \N 0 @@ -2027,6 +2723,21 @@ Monday 0 0 +-- !sql_days_diff_TimestampNs_DateTime -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_days_diff_DateTimeV2_DateTime_notnull -- 0 0 @@ -2041,6 +2752,20 @@ Monday 0 0 +-- !sql_days_diff_TimestampNs_DateTime_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_days_diff_DateTime_DateTimeV2 -- \N 0 @@ -2056,6 +2781,21 @@ Monday 0 0 +-- !sql_days_diff_DateTime_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_days_diff_DateTime_DateTimeV2_notnull -- 0 0 @@ -2070,6 +2810,20 @@ Monday 0 0 +-- !sql_days_diff_DateTime_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_days_sub_DateTimeV2_Integer -- \N 2012-02-29T01:00:01 @@ -2085,6 +2839,21 @@ Monday 2012-02-29T11:10:11 2012-02-29T12:11:12 +-- !sql_days_sub_TimestampNs_Integer -- +\N +2012-02-29 01:00:01.000000000 +2012-02-29 02:01:02.000000000 +2012-02-29 03:02:03.000000000 +2012-02-29 04:03:04.000000000 +2012-02-29 05:04:05.000000000 +2012-02-29 06:05:06.000000000 +2012-02-29 07:06:07.000000000 +2012-02-29 08:07:08.000000000 +2012-02-29 09:08:09.000000000 +2012-02-29 10:09:10.000000000 +2012-02-29 11:10:11.000000000 +2012-02-29 12:11:12.000000000 + -- !sql_days_sub_DateTimeV2_Integer_notnull -- 2012-02-29T01:00:01 2012-02-29T02:01:02 @@ -2099,6 +2868,20 @@ Monday 2012-02-29T11:10:11 2012-02-29T12:11:12 +-- !sql_days_sub_TimestampNs_Integer_notnull -- +2012-02-29 01:00:01.000000000 +2012-02-29 02:01:02.000000000 +2012-02-29 03:02:03.000000000 +2012-02-29 04:03:04.000000000 +2012-02-29 05:04:05.000000000 +2012-02-29 06:05:06.000000000 +2012-02-29 07:06:07.000000000 +2012-02-29 08:07:08.000000000 +2012-02-29 09:08:09.000000000 +2012-02-29 10:09:10.000000000 +2012-02-29 11:10:11.000000000 +2012-02-29 12:11:12.000000000 + -- !sql_days_sub_DateV2_Integer -- \N 2012-02-29 diff --git a/regression-test/data/nereids_function_p0/scalar_function/F.out b/regression-test/data/nereids_function_p0/scalar_function/F.out index 200956023370ec..c83e3cca5df058 100644 --- a/regression-test/data/nereids_function_p0/scalar_function/F.out +++ b/regression-test/data/nereids_function_p0/scalar_function/F.out @@ -275,6 +275,21 @@ 0 0 +-- !sql_field_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_field_DateTimeV2_notnull -- 0 0 @@ -289,6 +304,20 @@ 0 0 +-- !sql_field_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_field_Varchar -- 0 0 diff --git a/regression-test/data/nereids_function_p0/scalar_function/G.out b/regression-test/data/nereids_function_p0/scalar_function/G.out index 8516e17b8e5bd9..a8dd8da51ffa86 100644 --- a/regression-test/data/nereids_function_p0/scalar_function/G.out +++ b/regression-test/data/nereids_function_p0/scalar_function/G.out @@ -481,6 +481,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_greatest_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_greatest_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -495,6 +510,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_greatest_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_greatest_Varchar -- null varchar11 diff --git a/regression-test/data/nereids_function_p0/scalar_function/H.out b/regression-test/data/nereids_function_p0/scalar_function/H.out index 37a991748daab8..faafe21a5c4a7e 100644 --- a/regression-test/data/nereids_function_p0/scalar_function/H.out +++ b/regression-test/data/nereids_function_p0/scalar_function/H.out @@ -304,6 +304,21 @@ AQGO5rMmsc7hDA== 11 12 +-- !sql_hour_TimestampNs -- +\N +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 + -- !sql_hour_DateTimeV2_notnull -- 1 2 @@ -318,6 +333,20 @@ AQGO5rMmsc7hDA== 11 12 +-- !sql_hour_TimestampNs_notnull -- +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 + -- !sql_hour_DateV2 -- \N 0 @@ -391,6 +420,21 @@ AQGO5rMmsc7hDA== 2012-03-11T12:00 2012-03-12T13:00 +-- !sql_hour_ceil_TimestampNs -- +\N +2012-03-01 02:00:00.000000000 +2012-03-02 03:00:00.000000000 +2012-03-03 04:00:00.000000000 +2012-03-04 05:00:00.000000000 +2012-03-05 06:00:00.000000000 +2012-03-06 07:00:00.000000000 +2012-03-07 08:00:00.000000000 +2012-03-08 09:00:00.000000000 +2012-03-09 10:00:00.000000000 +2012-03-10 11:00:00.000000000 +2012-03-11 12:00:00.000000000 +2012-03-12 13:00:00.000000000 + -- !sql_hour_ceil_DateTimeV2_notnull -- 2012-03-01T02:00 2012-03-02T03:00 @@ -405,6 +449,20 @@ AQGO5rMmsc7hDA== 2012-03-11T12:00 2012-03-12T13:00 +-- !sql_hour_ceil_TimestampNs_notnull -- +2012-03-01 02:00:00.000000000 +2012-03-02 03:00:00.000000000 +2012-03-03 04:00:00.000000000 +2012-03-04 05:00:00.000000000 +2012-03-05 06:00:00.000000000 +2012-03-06 07:00:00.000000000 +2012-03-07 08:00:00.000000000 +2012-03-08 09:00:00.000000000 +2012-03-09 10:00:00.000000000 +2012-03-10 11:00:00.000000000 +2012-03-11 12:00:00.000000000 +2012-03-12 13:00:00.000000000 + -- !sql_hour_ceil_DateTime_DateTime -- \N 2012-03-01T01:00:01 @@ -478,6 +536,21 @@ AQGO5rMmsc7hDA== 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_hour_ceil_TimestampNs_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_hour_ceil_DateTimeV2_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -492,6 +565,20 @@ AQGO5rMmsc7hDA== 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_hour_ceil_TimestampNs_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_hour_ceil_DateTimeV2_Integer -- \N 2012-03-01T02:00 @@ -507,6 +594,21 @@ AQGO5rMmsc7hDA== 2012-03-11T16:00 2012-03-13T00:00 +-- !sql_hour_ceil_TimestampNs_Integer -- +\N +2012-03-01 02:00:00.000000000 +2012-03-02 04:00:00.000000000 +2012-03-03 06:00:00.000000000 +2012-03-04 08:00:00.000000000 +2012-03-05 06:00:00.000000000 +2012-03-06 12:00:00.000000000 +2012-03-07 08:00:00.000000000 +2012-03-08 16:00:00.000000000 +2012-03-09 15:00:00.000000000 +2012-03-10 16:00:00.000000000 +2012-03-11 16:00:00.000000000 +2012-03-13 00:00:00.000000000 + -- !sql_hour_ceil_DateTimeV2_Integer_notnull -- 2012-03-01T02:00 2012-03-02T04:00 @@ -521,6 +623,20 @@ AQGO5rMmsc7hDA== 2012-03-11T16:00 2012-03-13T00:00 +-- !sql_hour_ceil_TimestampNs_Integer_notnull -- +2012-03-01 02:00:00.000000000 +2012-03-02 04:00:00.000000000 +2012-03-03 06:00:00.000000000 +2012-03-04 08:00:00.000000000 +2012-03-05 06:00:00.000000000 +2012-03-06 12:00:00.000000000 +2012-03-07 08:00:00.000000000 +2012-03-08 16:00:00.000000000 +2012-03-09 15:00:00.000000000 +2012-03-10 16:00:00.000000000 +2012-03-11 16:00:00.000000000 +2012-03-13 00:00:00.000000000 + -- !sql_hour_ceil_DateTime_Integer_DateTime -- \N 2012-03-01T01:00:01 @@ -565,6 +681,21 @@ AQGO5rMmsc7hDA== 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_hour_ceil_TimestampNs_Integer_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_hour_ceil_DateTimeV2_Integer_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -579,6 +710,20 @@ AQGO5rMmsc7hDA== 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_hour_ceil_TimestampNs_Integer_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_hour_floor_DateTime -- \N 2012-03-01T01:00 @@ -623,6 +768,21 @@ AQGO5rMmsc7hDA== 2012-03-11T11:00 2012-03-12T12:00 +-- !sql_hour_floor_TimestampNs -- +\N +2012-03-01 01:00:00.000000000 +2012-03-02 02:00:00.000000000 +2012-03-03 03:00:00.000000000 +2012-03-04 04:00:00.000000000 +2012-03-05 05:00:00.000000000 +2012-03-06 06:00:00.000000000 +2012-03-07 07:00:00.000000000 +2012-03-08 08:00:00.000000000 +2012-03-09 09:00:00.000000000 +2012-03-10 10:00:00.000000000 +2012-03-11 11:00:00.000000000 +2012-03-12 12:00:00.000000000 + -- !sql_hour_floor_DateTimeV2_notnull -- 2012-03-01T01:00 2012-03-02T02:00 @@ -637,6 +797,20 @@ AQGO5rMmsc7hDA== 2012-03-11T11:00 2012-03-12T12:00 +-- !sql_hour_floor_TimestampNs_notnull -- +2012-03-01 01:00:00.000000000 +2012-03-02 02:00:00.000000000 +2012-03-03 03:00:00.000000000 +2012-03-04 04:00:00.000000000 +2012-03-05 05:00:00.000000000 +2012-03-06 06:00:00.000000000 +2012-03-07 07:00:00.000000000 +2012-03-08 08:00:00.000000000 +2012-03-09 09:00:00.000000000 +2012-03-10 10:00:00.000000000 +2012-03-11 11:00:00.000000000 +2012-03-12 12:00:00.000000000 + -- !sql_hour_floor_DateTime_DateTime -- \N 2012-03-01T01:00:01 @@ -710,6 +884,21 @@ AQGO5rMmsc7hDA== 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_hour_floor_TimestampNs_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_hour_floor_DateTimeV2_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -724,6 +913,20 @@ AQGO5rMmsc7hDA== 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_hour_floor_TimestampNs_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_hour_floor_DateTimeV2_Integer -- \N 2012-03-01T01:00 @@ -739,6 +942,21 @@ AQGO5rMmsc7hDA== 2012-03-11T05:00 2012-03-12T12:00 +-- !sql_hour_floor_TimestampNs_Integer -- +\N +2012-03-01 01:00:00.000000000 +2012-03-02 02:00:00.000000000 +2012-03-03 03:00:00.000000000 +2012-03-04 04:00:00.000000000 +2012-03-05 01:00:00.000000000 +2012-03-06 06:00:00.000000000 +2012-03-07 01:00:00.000000000 +2012-03-08 08:00:00.000000000 +2012-03-09 06:00:00.000000000 +2012-03-10 06:00:00.000000000 +2012-03-11 05:00:00.000000000 +2012-03-12 12:00:00.000000000 + -- !sql_hour_floor_DateTimeV2_Integer_notnull -- 2012-03-01T01:00 2012-03-02T02:00 @@ -753,6 +971,20 @@ AQGO5rMmsc7hDA== 2012-03-11T05:00 2012-03-12T12:00 +-- !sql_hour_floor_TimestampNs_Integer_notnull -- +2012-03-01 01:00:00.000000000 +2012-03-02 02:00:00.000000000 +2012-03-03 03:00:00.000000000 +2012-03-04 04:00:00.000000000 +2012-03-05 01:00:00.000000000 +2012-03-06 06:00:00.000000000 +2012-03-07 01:00:00.000000000 +2012-03-08 08:00:00.000000000 +2012-03-09 06:00:00.000000000 +2012-03-10 06:00:00.000000000 +2012-03-11 05:00:00.000000000 +2012-03-12 12:00:00.000000000 + -- !sql_hour_floor_DateTime_Integer_DateTime -- \N 2012-03-01T01:00:01 @@ -797,6 +1029,21 @@ AQGO5rMmsc7hDA== 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_hour_floor_TimestampNs_Integer_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_hour_floor_DateTimeV2_Integer_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -811,6 +1058,20 @@ AQGO5rMmsc7hDA== 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_hour_floor_TimestampNs_Integer_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_hours_add_DateTime_Integer -- \N 2012-03-01T02:00:01 @@ -855,6 +1116,21 @@ AQGO5rMmsc7hDA== 2012-03-11T22:10:11 2012-03-13T00:11:12 +-- !sql_hours_add_TimestampNs_Integer -- +\N +2012-03-01 02:00:01.000000000 +2012-03-02 04:01:02.000000000 +2012-03-03 06:02:03.000000000 +2012-03-04 08:03:04.000000000 +2012-03-05 10:04:05.000000000 +2012-03-06 12:05:06.000000000 +2012-03-07 14:06:07.000000000 +2012-03-08 16:07:08.000000000 +2012-03-09 18:08:09.000000000 +2012-03-10 20:09:10.000000000 +2012-03-11 22:10:11.000000000 +2012-03-13 00:11:12.000000000 + -- !sql_hours_add_DateTimeV2_Integer_notnull -- 2012-03-01T02:00:01 2012-03-02T04:01:02 @@ -869,6 +1145,20 @@ AQGO5rMmsc7hDA== 2012-03-11T22:10:11 2012-03-13T00:11:12 +-- !sql_hours_add_TimestampNs_Integer_notnull -- +2012-03-01 02:00:01.000000000 +2012-03-02 04:01:02.000000000 +2012-03-03 06:02:03.000000000 +2012-03-04 08:03:04.000000000 +2012-03-05 10:04:05.000000000 +2012-03-06 12:05:06.000000000 +2012-03-07 14:06:07.000000000 +2012-03-08 16:07:08.000000000 +2012-03-09 18:08:09.000000000 +2012-03-10 20:09:10.000000000 +2012-03-11 22:10:11.000000000 +2012-03-13 00:11:12.000000000 + -- !sql_hours_add_Date_Integer -- \N 2012-03-01T01:00 @@ -971,6 +1261,21 @@ AQGO5rMmsc7hDA== 0 0 +-- !sql_hours_diff_TimestampNs_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_hours_diff_DateTimeV2_DateTimeV2_notnull -- 0 0 @@ -985,6 +1290,20 @@ AQGO5rMmsc7hDA== 0 0 +-- !sql_hours_diff_TimestampNs_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_hours_diff_DateV2_DateTimeV2 -- \N -1 @@ -1000,6 +1319,21 @@ AQGO5rMmsc7hDA== -11 -12 +-- !sql_hours_diff_DateV2_TimestampNs -- +\N +-1 +-2 +-3 +-4 +-5 +-6 +-7 +-8 +-9 +-10 +-11 +-12 + -- !sql_hours_diff_DateV2_DateTimeV2_notnull -- -1 -2 @@ -1014,6 +1348,20 @@ AQGO5rMmsc7hDA== -11 -12 +-- !sql_hours_diff_DateV2_TimestampNs_notnull -- +-1 +-2 +-3 +-4 +-5 +-6 +-7 +-8 +-9 +-10 +-11 +-12 + -- !sql_hours_diff_DateTimeV2_DateV2 -- \N 1 @@ -1029,6 +1377,21 @@ AQGO5rMmsc7hDA== 11 12 +-- !sql_hours_diff_TimestampNs_DateV2 -- +\N +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 + -- !sql_hours_diff_DateTimeV2_DateV2_notnull -- 1 2 @@ -1043,6 +1406,20 @@ AQGO5rMmsc7hDA== 11 12 +-- !sql_hours_diff_TimestampNs_DateV2_notnull -- +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 + -- !sql_hours_diff_DateV2_DateV2 -- \N 0 @@ -1145,6 +1522,21 @@ AQGO5rMmsc7hDA== 0 0 +-- !sql_hours_diff_TimestampNs_DateTime -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_hours_diff_DateTimeV2_DateTime_notnull -- 0 0 @@ -1159,6 +1551,20 @@ AQGO5rMmsc7hDA== 0 0 +-- !sql_hours_diff_TimestampNs_DateTime_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_hours_diff_DateTime_DateTimeV2 -- \N 0 @@ -1174,6 +1580,21 @@ AQGO5rMmsc7hDA== 0 0 +-- !sql_hours_diff_DateTime_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_hours_diff_DateTime_DateTimeV2_notnull -- 0 0 @@ -1188,6 +1609,20 @@ AQGO5rMmsc7hDA== 0 0 +-- !sql_hours_diff_DateTime_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_hours_sub_DateTime_Integer -- \N 2012-03-01T00:00:01 @@ -1232,6 +1667,21 @@ AQGO5rMmsc7hDA== 2012-03-11T00:10:11 2012-03-12T00:11:12 +-- !sql_hours_sub_TimestampNs_Integer -- +\N +2012-03-01 00:00:01.000000000 +2012-03-02 00:01:02.000000000 +2012-03-03 00:02:03.000000000 +2012-03-04 00:03:04.000000000 +2012-03-05 00:04:05.000000000 +2012-03-06 00:05:06.000000000 +2012-03-07 00:06:07.000000000 +2012-03-08 00:07:08.000000000 +2012-03-09 00:08:09.000000000 +2012-03-10 00:09:10.000000000 +2012-03-11 00:10:11.000000000 +2012-03-12 00:11:12.000000000 + -- !sql_hours_sub_DateTimeV2_Integer_notnull -- 2012-03-01T00:00:01 2012-03-02T00:01:02 @@ -1246,6 +1696,20 @@ AQGO5rMmsc7hDA== 2012-03-11T00:10:11 2012-03-12T00:11:12 +-- !sql_hours_sub_TimestampNs_Integer_notnull -- +2012-03-01 00:00:01.000000000 +2012-03-02 00:01:02.000000000 +2012-03-03 00:02:03.000000000 +2012-03-04 00:03:04.000000000 +2012-03-05 00:04:05.000000000 +2012-03-06 00:05:06.000000000 +2012-03-07 00:06:07.000000000 +2012-03-08 00:07:08.000000000 +2012-03-09 00:08:09.000000000 +2012-03-10 00:09:10.000000000 +2012-03-11 00:10:11.000000000 +2012-03-12 00:11:12.000000000 + -- !sql_hours_sub_Date_Integer -- \N 2012-02-29T23:00 diff --git a/regression-test/data/nereids_function_p0/scalar_function/L.out b/regression-test/data/nereids_function_p0/scalar_function/L.out index e9a7a96a072d08..07683944b03659 100644 --- a/regression-test/data/nereids_function_p0/scalar_function/L.out +++ b/regression-test/data/nereids_function_p0/scalar_function/L.out @@ -72,6 +72,21 @@ 2012-03-31 2012-03-31 +-- !sql_last_day_TimestampNs -- +\N +2012-03-31 +2012-03-31 +2012-03-31 +2012-03-31 +2012-03-31 +2012-03-31 +2012-03-31 +2012-03-31 +2012-03-31 +2012-03-31 +2012-03-31 +2012-03-31 + -- !sql_last_day_DateTimeV2_notnull -- 2012-03-31 2012-03-31 @@ -86,6 +101,20 @@ 2012-03-31 2012-03-31 +-- !sql_last_day_TimestampNs_notnull -- +2012-03-31 +2012-03-31 +2012-03-31 +2012-03-31 +2012-03-31 +2012-03-31 +2012-03-31 +2012-03-31 +2012-03-31 +2012-03-31 +2012-03-31 +2012-03-31 + -- !sql_last_day_DateV2 -- \N 2012-03-31 @@ -565,6 +594,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_least_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_least_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -579,6 +623,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_least_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_least_DecimalV2 -- \N 0.100 diff --git a/regression-test/data/nereids_function_p0/scalar_function/M.out b/regression-test/data/nereids_function_p0/scalar_function/M.out index 1b66c338a09dd3..20c8ad4e76151b 100644 --- a/regression-test/data/nereids_function_p0/scalar_function/M.out +++ b/regression-test/data/nereids_function_p0/scalar_function/M.out @@ -362,6 +362,21 @@ dc5f80c371451aa4fc81c930adc64f60 10 11 +-- !sql_minute_TimestampNs -- +\N +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 + -- !sql_minute_DateTimeV2_notnull -- 0 1 @@ -376,6 +391,20 @@ dc5f80c371451aa4fc81c930adc64f60 10 11 +-- !sql_minute_TimestampNs_notnull -- +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 + -- !sql_minute_DateV2 -- \N 0 @@ -449,6 +478,21 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:11 2012-03-12T12:12 +-- !sql_minute_ceil_TimestampNs -- +\N +2012-03-01 01:01:00.000000000 +2012-03-02 02:02:00.000000000 +2012-03-03 03:03:00.000000000 +2012-03-04 04:04:00.000000000 +2012-03-05 05:05:00.000000000 +2012-03-06 06:06:00.000000000 +2012-03-07 07:07:00.000000000 +2012-03-08 08:08:00.000000000 +2012-03-09 09:09:00.000000000 +2012-03-10 10:10:00.000000000 +2012-03-11 11:11:00.000000000 +2012-03-12 12:12:00.000000000 + -- !sql_minute_ceil_DateTimeV2_notnull -- 2012-03-01T01:01 2012-03-02T02:02 @@ -463,6 +507,20 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:11 2012-03-12T12:12 +-- !sql_minute_ceil_TimestampNs_notnull -- +2012-03-01 01:01:00.000000000 +2012-03-02 02:02:00.000000000 +2012-03-03 03:03:00.000000000 +2012-03-04 04:04:00.000000000 +2012-03-05 05:05:00.000000000 +2012-03-06 06:06:00.000000000 +2012-03-07 07:07:00.000000000 +2012-03-08 08:08:00.000000000 +2012-03-09 09:09:00.000000000 +2012-03-10 10:10:00.000000000 +2012-03-11 11:11:00.000000000 +2012-03-12 12:12:00.000000000 + -- !sql_minute_ceil_DateTime_DateTime -- \N 2012-03-01T01:00:01 @@ -536,6 +594,21 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_minute_ceil_TimestampNs_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_minute_ceil_DateTimeV2_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -550,6 +623,20 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_minute_ceil_TimestampNs_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_minute_ceil_DateTimeV2_Integer -- \N 2012-03-01T01:01 @@ -565,6 +652,21 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:14 2012-03-12T12:12 +-- !sql_minute_ceil_TimestampNs_Integer -- +\N +2012-03-01 01:01:00.000000000 +2012-03-02 02:02:00.000000000 +2012-03-03 03:03:00.000000000 +2012-03-04 04:04:00.000000000 +2012-03-05 05:05:00.000000000 +2012-03-06 06:06:00.000000000 +2012-03-07 07:11:00.000000000 +2012-03-08 08:08:00.000000000 +2012-03-09 09:09:00.000000000 +2012-03-10 10:10:00.000000000 +2012-03-11 11:14:00.000000000 +2012-03-12 12:12:00.000000000 + -- !sql_minute_ceil_DateTimeV2_Integer_notnull -- 2012-03-01T01:01 2012-03-02T02:02 @@ -579,6 +681,20 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:14 2012-03-12T12:12 +-- !sql_minute_ceil_TimestampNs_Integer_notnull -- +2012-03-01 01:01:00.000000000 +2012-03-02 02:02:00.000000000 +2012-03-03 03:03:00.000000000 +2012-03-04 04:04:00.000000000 +2012-03-05 05:05:00.000000000 +2012-03-06 06:06:00.000000000 +2012-03-07 07:11:00.000000000 +2012-03-08 08:08:00.000000000 +2012-03-09 09:09:00.000000000 +2012-03-10 10:10:00.000000000 +2012-03-11 11:14:00.000000000 +2012-03-12 12:12:00.000000000 + -- !sql_minute_ceil_DateTime_Integer_DateTime -- \N 2012-03-01T01:00:01 @@ -623,6 +739,21 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_minute_ceil_TimestampNs_Integer_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_minute_ceil_DateTimeV2_Integer_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -637,6 +768,20 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_minute_ceil_TimestampNs_Integer_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_minute_floor_DateTime -- \N 2012-03-01T01:00 @@ -681,6 +826,21 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:10 2012-03-12T12:11 +-- !sql_minute_floor_TimestampNs -- +\N +2012-03-01 01:00:00.000000000 +2012-03-02 02:01:00.000000000 +2012-03-03 03:02:00.000000000 +2012-03-04 04:03:00.000000000 +2012-03-05 05:04:00.000000000 +2012-03-06 06:05:00.000000000 +2012-03-07 07:06:00.000000000 +2012-03-08 08:07:00.000000000 +2012-03-09 09:08:00.000000000 +2012-03-10 10:09:00.000000000 +2012-03-11 11:10:00.000000000 +2012-03-12 12:11:00.000000000 + -- !sql_minute_floor_DateTimeV2_notnull -- 2012-03-01T01:00 2012-03-02T02:01 @@ -695,6 +855,20 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:10 2012-03-12T12:11 +-- !sql_minute_floor_TimestampNs_notnull -- +2012-03-01 01:00:00.000000000 +2012-03-02 02:01:00.000000000 +2012-03-03 03:02:00.000000000 +2012-03-04 04:03:00.000000000 +2012-03-05 05:04:00.000000000 +2012-03-06 06:05:00.000000000 +2012-03-07 07:06:00.000000000 +2012-03-08 08:07:00.000000000 +2012-03-09 09:08:00.000000000 +2012-03-10 10:09:00.000000000 +2012-03-11 11:10:00.000000000 +2012-03-12 12:11:00.000000000 + -- !sql_minute_floor_DateTime_DateTime -- \N 2012-03-01T01:00:01 @@ -768,6 +942,21 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_minute_floor_TimestampNs_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_minute_floor_DateTimeV2_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -782,6 +971,20 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_minute_floor_TimestampNs_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_minute_floor_DateTimeV2_Integer -- \N 2012-03-01T01:00 @@ -797,6 +1000,21 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:03 2012-03-12T12:00 +-- !sql_minute_floor_TimestampNs_Integer -- +\N +2012-03-01 01:00:00.000000000 +2012-03-02 02:00:00.000000000 +2012-03-03 03:00:00.000000000 +2012-03-04 04:00:00.000000000 +2012-03-05 05:00:00.000000000 +2012-03-06 06:00:00.000000000 +2012-03-07 07:04:00.000000000 +2012-03-08 08:00:00.000000000 +2012-03-09 09:00:00.000000000 +2012-03-10 10:00:00.000000000 +2012-03-11 11:03:00.000000000 +2012-03-12 12:00:00.000000000 + -- !sql_minute_floor_DateTimeV2_Integer_notnull -- 2012-03-01T01:00 2012-03-02T02:00 @@ -811,6 +1029,20 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:03 2012-03-12T12:00 +-- !sql_minute_floor_TimestampNs_Integer_notnull -- +2012-03-01 01:00:00.000000000 +2012-03-02 02:00:00.000000000 +2012-03-03 03:00:00.000000000 +2012-03-04 04:00:00.000000000 +2012-03-05 05:00:00.000000000 +2012-03-06 06:00:00.000000000 +2012-03-07 07:04:00.000000000 +2012-03-08 08:00:00.000000000 +2012-03-09 09:00:00.000000000 +2012-03-10 10:00:00.000000000 +2012-03-11 11:03:00.000000000 +2012-03-12 12:00:00.000000000 + -- !sql_minute_floor_DateTime_Integer_DateTime -- \N 2012-03-01T01:00:01 @@ -855,6 +1087,21 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_minute_floor_TimestampNs_Integer_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_minute_floor_DateTimeV2_Integer_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -869,6 +1116,20 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_minute_floor_TimestampNs_Integer_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_minutes_add_DateTime_Integer -- \N 2012-03-01T01:01:01 @@ -913,6 +1174,21 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:21:11 2012-03-12T12:23:12 +-- !sql_minutes_add_TimestampNs_Integer -- +\N +2012-03-01 01:01:01.000000000 +2012-03-02 02:03:02.000000000 +2012-03-03 03:05:03.000000000 +2012-03-04 04:07:04.000000000 +2012-03-05 05:09:05.000000000 +2012-03-06 06:11:06.000000000 +2012-03-07 07:13:07.000000000 +2012-03-08 08:15:08.000000000 +2012-03-09 09:17:09.000000000 +2012-03-10 10:19:10.000000000 +2012-03-11 11:21:11.000000000 +2012-03-12 12:23:12.000000000 + -- !sql_minutes_add_DateTimeV2_Integer_notnull -- 2012-03-01T01:01:01 2012-03-02T02:03:02 @@ -927,6 +1203,20 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:21:11 2012-03-12T12:23:12 +-- !sql_minutes_add_TimestampNs_Integer_notnull -- +2012-03-01 01:01:01.000000000 +2012-03-02 02:03:02.000000000 +2012-03-03 03:05:03.000000000 +2012-03-04 04:07:04.000000000 +2012-03-05 05:09:05.000000000 +2012-03-06 06:11:06.000000000 +2012-03-07 07:13:07.000000000 +2012-03-08 08:15:08.000000000 +2012-03-09 09:17:09.000000000 +2012-03-10 10:19:10.000000000 +2012-03-11 11:21:11.000000000 +2012-03-12 12:23:12.000000000 + -- !sql_minutes_add_Date_Integer -- \N 2012-03-01T00:01 @@ -1029,6 +1319,21 @@ dc5f80c371451aa4fc81c930adc64f60 0 0 +-- !sql_minutes_diff_TimestampNs_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_minutes_diff_DateTimeV2_DateTimeV2_notnull -- 0 0 @@ -1043,6 +1348,20 @@ dc5f80c371451aa4fc81c930adc64f60 0 0 +-- !sql_minutes_diff_TimestampNs_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_minutes_diff_DateV2_DateTimeV2 -- \N -60 @@ -1058,6 +1377,21 @@ dc5f80c371451aa4fc81c930adc64f60 -670 -731 +-- !sql_minutes_diff_DateV2_TimestampNs -- +\N +-60 +-121 +-182 +-243 +-304 +-365 +-426 +-487 +-548 +-609 +-670 +-731 + -- !sql_minutes_diff_DateV2_DateTimeV2_notnull -- -60 -121 @@ -1072,6 +1406,20 @@ dc5f80c371451aa4fc81c930adc64f60 -670 -731 +-- !sql_minutes_diff_DateV2_TimestampNs_notnull -- +-60 +-121 +-182 +-243 +-304 +-365 +-426 +-487 +-548 +-609 +-670 +-731 + -- !sql_minutes_diff_DateTimeV2_DateV2 -- \N 60 @@ -1087,6 +1435,21 @@ dc5f80c371451aa4fc81c930adc64f60 670 731 +-- !sql_minutes_diff_TimestampNs_DateV2 -- +\N +60 +121 +182 +243 +304 +365 +426 +487 +548 +609 +670 +731 + -- !sql_minutes_diff_DateTimeV2_DateV2_notnull -- 60 121 @@ -1101,6 +1464,20 @@ dc5f80c371451aa4fc81c930adc64f60 670 731 +-- !sql_minutes_diff_TimestampNs_DateV2_notnull -- +60 +121 +182 +243 +304 +365 +426 +487 +548 +609 +670 +731 + -- !sql_minutes_diff_DateV2_DateV2 -- \N 0 @@ -1203,6 +1580,21 @@ dc5f80c371451aa4fc81c930adc64f60 0 0 +-- !sql_minutes_diff_TimestampNs_DateTime -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_minutes_diff_DateTimeV2_DateTime_notnull -- 0 0 @@ -1217,6 +1609,20 @@ dc5f80c371451aa4fc81c930adc64f60 0 0 +-- !sql_minutes_diff_TimestampNs_DateTime_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_minutes_diff_DateTime_DateTimeV2 -- \N 0 @@ -1232,6 +1638,21 @@ dc5f80c371451aa4fc81c930adc64f60 0 0 +-- !sql_minutes_diff_DateTime_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_minutes_diff_DateTime_DateTimeV2_notnull -- 0 0 @@ -1246,6 +1667,20 @@ dc5f80c371451aa4fc81c930adc64f60 0 0 +-- !sql_minutes_diff_DateTime_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_minutes_sub_DateTime_Integer -- \N 2012-03-01T00:59:01 @@ -1290,6 +1725,21 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T10:59:11 2012-03-12T11:59:12 +-- !sql_minutes_sub_TimestampNs_Integer -- +\N +2012-03-01 00:59:01.000000000 +2012-03-02 01:59:02.000000000 +2012-03-03 02:59:03.000000000 +2012-03-04 03:59:04.000000000 +2012-03-05 04:59:05.000000000 +2012-03-06 05:59:06.000000000 +2012-03-07 06:59:07.000000000 +2012-03-08 07:59:08.000000000 +2012-03-09 08:59:09.000000000 +2012-03-10 09:59:10.000000000 +2012-03-11 10:59:11.000000000 +2012-03-12 11:59:12.000000000 + -- !sql_minutes_sub_DateTimeV2_Integer_notnull -- 2012-03-01T00:59:01 2012-03-02T01:59:02 @@ -1304,6 +1754,20 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T10:59:11 2012-03-12T11:59:12 +-- !sql_minutes_sub_TimestampNs_Integer_notnull -- +2012-03-01 00:59:01.000000000 +2012-03-02 01:59:02.000000000 +2012-03-03 02:59:03.000000000 +2012-03-04 03:59:04.000000000 +2012-03-05 04:59:05.000000000 +2012-03-06 05:59:06.000000000 +2012-03-07 06:59:07.000000000 +2012-03-08 07:59:08.000000000 +2012-03-09 08:59:09.000000000 +2012-03-10 09:59:10.000000000 +2012-03-11 10:59:11.000000000 +2012-03-12 11:59:12.000000000 + -- !sql_minutes_sub_Date_Integer -- \N 2012-02-29T23:59 @@ -1522,6 +1986,21 @@ dc5f80c371451aa4fc81c930adc64f60 3 3 +-- !sql_month_TimestampNs -- +\N +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 + -- !sql_month_DateTimeV2_notnull -- 3 3 @@ -1536,6 +2015,20 @@ dc5f80c371451aa4fc81c930adc64f60 3 3 +-- !sql_month_TimestampNs_notnull -- +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 + -- !sql_month_DateV2 -- \N 3 @@ -1612,6 +2105,21 @@ dc5f80c371451aa4fc81c930adc64f60 2012-04-01T00:00 2012-04-01T00:00 +-- !sql_month_ceil_TimestampNs -- +\N +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 + -- !sql_month_ceil_DateTimeV2_notnull -- 2012-04-01T00:00 2012-04-01T00:00 @@ -1626,6 +2134,20 @@ dc5f80c371451aa4fc81c930adc64f60 2012-04-01T00:00 2012-04-01T00:00 +-- !sql_month_ceil_TimestampNs_notnull -- +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 + -- !sql_month_ceil_DateV2 -- \N 2012-03-01 @@ -1728,6 +2250,21 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_month_ceil_TimestampNs_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_month_ceil_DateTimeV2_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -1742,6 +2279,20 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_month_ceil_TimestampNs_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_month_ceil_DateTimeV2_Integer -- \N 2012-04-01T00:00 @@ -1757,6 +2308,21 @@ dc5f80c371451aa4fc81c930adc64f60 2013-02-01T00:00 2013-01-01T00:00 +-- !sql_month_ceil_TimestampNs_Integer -- +\N +2012-04-01 00:00:00.000000000 +2012-05-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-05-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-07-01 00:00:00.000000000 +2012-05-01 00:00:00.000000000 +2012-05-01 00:00:00.000000000 +2012-07-01 00:00:00.000000000 +2012-09-01 00:00:00.000000000 +2013-02-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 + -- !sql_month_ceil_DateTimeV2_Integer_notnull -- 2012-04-01T00:00 2012-05-01T00:00 @@ -1771,6 +2337,20 @@ dc5f80c371451aa4fc81c930adc64f60 2013-02-01T00:00 2013-01-01T00:00 +-- !sql_month_ceil_TimestampNs_Integer_notnull -- +2012-04-01 00:00:00.000000000 +2012-05-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-05-01 00:00:00.000000000 +2012-04-01 00:00:00.000000000 +2012-07-01 00:00:00.000000000 +2012-05-01 00:00:00.000000000 +2012-05-01 00:00:00.000000000 +2012-07-01 00:00:00.000000000 +2012-09-01 00:00:00.000000000 +2013-02-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 + -- !sql_month_ceil_DateV2_DateV2 -- \N 2012-03-01 @@ -1873,6 +2453,21 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_month_ceil_TimestampNs_Integer_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_month_ceil_DateTimeV2_Integer_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -1887,6 +2482,20 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_month_ceil_TimestampNs_Integer_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_month_ceil_DateV2_Integer_DateV2 -- \N 2012-03-01 @@ -1960,6 +2569,21 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-01T00:00 2012-03-01T00:00 +-- !sql_month_floor_TimestampNs -- +\N +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 + -- !sql_month_floor_DateTimeV2_notnull -- 2012-03-01T00:00 2012-03-01T00:00 @@ -1974,6 +2598,20 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-01T00:00 2012-03-01T00:00 +-- !sql_month_floor_TimestampNs_notnull -- +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 + -- !sql_month_floor_DateV2 -- \N 2012-03-01 @@ -2076,6 +2714,21 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_month_floor_TimestampNs_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_month_floor_DateTimeV2_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -2090,6 +2743,20 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_month_floor_TimestampNs_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_month_floor_DateTimeV2_Integer -- \N 2012-03-01T00:00 @@ -2105,6 +2772,21 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-01T00:00 2012-01-01T00:00 +-- !sql_month_floor_TimestampNs_Integer -- +\N +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2011-11-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2011-10-01 00:00:00.000000000 +2011-09-01 00:00:00.000000000 +2011-10-01 00:00:00.000000000 +2011-11-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 + -- !sql_month_floor_DateTimeV2_Integer_notnull -- 2012-03-01T00:00 2012-03-01T00:00 @@ -2119,6 +2801,20 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-01T00:00 2012-01-01T00:00 +-- !sql_month_floor_TimestampNs_Integer_notnull -- +2012-03-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2011-11-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2011-10-01 00:00:00.000000000 +2011-09-01 00:00:00.000000000 +2011-10-01 00:00:00.000000000 +2011-11-01 00:00:00.000000000 +2012-03-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 + -- !sql_month_floor_DateV2_DateV2 -- \N 2012-03-01 @@ -2221,6 +2917,21 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_month_floor_TimestampNs_Integer_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_month_floor_DateTimeV2_Integer_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -2235,6 +2946,20 @@ dc5f80c371451aa4fc81c930adc64f60 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_month_floor_TimestampNs_Integer_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_month_floor_DateV2_Integer_DateV2 -- \N 2012-03-01 @@ -2308,6 +3033,21 @@ March March March +-- !sql_monthname_TimestampNs -- +\N +March +March +March +March +March +March +March +March +March +March +March +March + -- !sql_monthname_DateTimeV2_notnull -- March March @@ -2322,6 +3062,20 @@ March March March +-- !sql_monthname_TimestampNs_notnull -- +March +March +March +March +March +March +March +March +March +March +March +March + -- !sql_monthname_DateV2 -- \N March @@ -2395,6 +3149,21 @@ March 2013-02-11T11:10:11 2013-03-12T12:11:12 +-- !sql_months_add_TimestampNs_Integer -- +\N +2012-04-01 01:00:01.000000000 +2012-05-02 02:01:02.000000000 +2012-06-03 03:02:03.000000000 +2012-07-04 04:03:04.000000000 +2012-08-05 05:04:05.000000000 +2012-09-06 06:05:06.000000000 +2012-10-07 07:06:07.000000000 +2012-11-08 08:07:08.000000000 +2012-12-09 09:08:09.000000000 +2013-01-10 10:09:10.000000000 +2013-02-11 11:10:11.000000000 +2013-03-12 12:11:12.000000000 + -- !sql_months_add_DateTimeV2_Integer_notnull -- 2012-04-01T01:00:01 2012-05-02T02:01:02 @@ -2409,6 +3178,20 @@ March 2013-02-11T11:10:11 2013-03-12T12:11:12 +-- !sql_months_add_TimestampNs_Integer_notnull -- +2012-04-01 01:00:01.000000000 +2012-05-02 02:01:02.000000000 +2012-06-03 03:02:03.000000000 +2012-07-04 04:03:04.000000000 +2012-08-05 05:04:05.000000000 +2012-09-06 06:05:06.000000000 +2012-10-07 07:06:07.000000000 +2012-11-08 08:07:08.000000000 +2012-12-09 09:08:09.000000000 +2013-01-10 10:09:10.000000000 +2013-02-11 11:10:11.000000000 +2013-03-12 12:11:12.000000000 + -- !sql_months_add_Date_Integer -- \N 2012-04-01 @@ -2511,6 +3294,21 @@ March 0 0 +-- !sql_months_diff_TimestampNs_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_months_diff_DateTimeV2_DateTimeV2_notnull -- 0 0 @@ -2525,6 +3323,20 @@ March 0 0 +-- !sql_months_diff_TimestampNs_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_months_diff_DateV2_DateTimeV2 -- \N 0 @@ -2540,6 +3352,21 @@ March 0 0 +-- !sql_months_diff_DateV2_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_months_diff_DateV2_DateTimeV2_notnull -- 0 0 @@ -2554,6 +3381,20 @@ March 0 0 +-- !sql_months_diff_DateV2_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_months_diff_DateTimeV2_DateV2 -- \N 0 @@ -2569,6 +3410,21 @@ March 0 0 +-- !sql_months_diff_TimestampNs_DateV2 -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_months_diff_DateTimeV2_DateV2_notnull -- 0 0 @@ -2583,6 +3439,20 @@ March 0 0 +-- !sql_months_diff_TimestampNs_DateV2_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_months_diff_DateV2_DateV2 -- \N 0 @@ -2685,6 +3555,21 @@ March 0 0 +-- !sql_months_diff_TimestampNs_DateTime -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_months_diff_DateTimeV2_DateTime_notnull -- 0 0 @@ -2699,6 +3584,20 @@ March 0 0 +-- !sql_months_diff_TimestampNs_DateTime_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_months_diff_DateTime_DateTimeV2 -- \N 0 @@ -2714,6 +3613,21 @@ March 0 0 +-- !sql_months_diff_DateTime_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_months_diff_DateTime_DateTimeV2_notnull -- 0 0 @@ -2728,6 +3642,20 @@ March 0 0 +-- !sql_months_diff_DateTime_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_months_sub_DateTime_Integer -- \N 2012-02-01T01:00:01 @@ -2772,6 +3700,21 @@ March 2011-04-11T11:10:11 2011-03-12T12:11:12 +-- !sql_months_sub_TimestampNs_Integer -- +\N +2012-02-01 01:00:01.000000000 +2012-01-02 02:01:02.000000000 +2011-12-03 03:02:03.000000000 +2011-11-04 04:03:04.000000000 +2011-10-05 05:04:05.000000000 +2011-09-06 06:05:06.000000000 +2011-08-07 07:06:07.000000000 +2011-07-08 08:07:08.000000000 +2011-06-09 09:08:09.000000000 +2011-05-10 10:09:10.000000000 +2011-04-11 11:10:11.000000000 +2011-03-12 12:11:12.000000000 + -- !sql_months_sub_DateTimeV2_Integer_notnull -- 2012-02-01T01:00:01 2012-01-02T02:01:02 @@ -2786,6 +3729,20 @@ March 2011-04-11T11:10:11 2011-03-12T12:11:12 +-- !sql_months_sub_TimestampNs_Integer_notnull -- +2012-02-01 01:00:01.000000000 +2012-01-02 02:01:02.000000000 +2011-12-03 03:02:03.000000000 +2011-11-04 04:03:04.000000000 +2011-10-05 05:04:05.000000000 +2011-09-06 06:05:06.000000000 +2011-08-07 07:06:07.000000000 +2011-07-08 08:07:08.000000000 +2011-06-09 09:08:09.000000000 +2011-05-10 10:09:10.000000000 +2011-04-11 11:10:11.000000000 +2011-03-12 12:11:12.000000000 + -- !sql_months_sub_Date_Integer -- \N 2012-02-01 diff --git a/regression-test/data/nereids_function_p0/scalar_function/N.out b/regression-test/data/nereids_function_p0/scalar_function/N.out index 1cfd80275cd9d5..5524b072a9d3e7 100644 --- a/regression-test/data/nereids_function_p0/scalar_function/N.out +++ b/regression-test/data/nereids_function_p0/scalar_function/N.out @@ -507,6 +507,21 @@ false \N \N +-- !sql_nullif_TimestampNs_TimestampNs -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N + -- !sql_nullif_DateTimeV2_DateTimeV2_notnull -- \N \N @@ -521,6 +536,20 @@ false \N \N +-- !sql_nullif_TimestampNs_TimestampNs_notnull -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N + -- !sql_nullif_DateV2_DateV2 -- \N \N @@ -1000,6 +1029,21 @@ true 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_nvl_TimestampNs_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_nvl_DateTimeV2_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -1014,6 +1058,20 @@ true 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_nvl_TimestampNs_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_nvl_DateV2_DateV2 -- \N 2012-03-01 diff --git a/regression-test/data/nereids_function_p0/scalar_function/Q.out b/regression-test/data/nereids_function_p0/scalar_function/Q.out index ba352849b92f1b..c6aafd91ef9893 100644 --- a/regression-test/data/nereids_function_p0/scalar_function/Q.out +++ b/regression-test/data/nereids_function_p0/scalar_function/Q.out @@ -43,6 +43,21 @@ 1 1 +-- !sql_quarter_TimestampNs -- +\N +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 + -- !sql_quarter_DateTimeV2_notnull -- 1 1 @@ -57,6 +72,20 @@ 1 1 +-- !sql_quarter_TimestampNs_notnull -- +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 + -- !sql_quarter_DateV2 -- \N 1 diff --git a/regression-test/data/nereids_function_p0/scalar_function/S.out b/regression-test/data/nereids_function_p0/scalar_function/S.out index e339f13bd5e072..639749c28e081a 100644 --- a/regression-test/data/nereids_function_p0/scalar_function/S.out +++ b/regression-test/data/nereids_function_p0/scalar_function/S.out @@ -43,6 +43,21 @@ 11 12 +-- !sql_second_TimestampNs -- +\N +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 + -- !sql_second_DateTimeV2_notnull -- 1 2 @@ -57,6 +72,20 @@ 11 12 +-- !sql_second_TimestampNs_notnull -- +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 + -- !sql_second_DateV2 -- \N 0 @@ -139,6 +168,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_second_ceil_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_second_ceil_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -153,6 +197,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_second_ceil_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_second_ceil_DateTime_DateTime -- \N 2012-03-01T01:00:01 @@ -226,6 +284,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_second_ceil_TimestampNs_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_second_ceil_DateTimeV2_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -240,6 +313,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_second_ceil_TimestampNs_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_second_ceil_DateTimeV2_Integer -- \N 2012-03-01T01:00:01 @@ -255,6 +342,21 @@ 2012-03-11T11:10:20 2012-03-12T12:11:12 +-- !sql_second_ceil_TimestampNs_Integer -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:13.000000000 +2012-03-08 08:07:12.000000000 +2012-03-09 09:08:15.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:20.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_second_ceil_DateTimeV2_Integer_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -269,6 +371,20 @@ 2012-03-11T11:10:20 2012-03-12T12:11:12 +-- !sql_second_ceil_TimestampNs_Integer_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:13.000000000 +2012-03-08 08:07:12.000000000 +2012-03-09 09:08:15.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:20.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_second_ceil_DateTime_Integer_DateTime -- \N 2012-03-01T01:00:01 @@ -313,6 +429,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_second_ceil_TimestampNs_Integer_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_second_ceil_DateTimeV2_Integer_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -327,6 +458,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_second_ceil_TimestampNs_Integer_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_second_floor_DateTime -- \N 2012-03-01T01:00:01 @@ -371,6 +516,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_second_floor_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_second_floor_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -385,6 +545,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_second_floor_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_second_floor_DateTime_DateTime -- \N 2012-03-01T01:00:01 @@ -458,6 +632,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_second_floor_TimestampNs_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_second_floor_DateTimeV2_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -472,6 +661,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_second_floor_TimestampNs_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_second_floor_DateTimeV2_Integer -- \N 2012-03-01T01:00:01 @@ -487,6 +690,21 @@ 2012-03-11T11:10:09 2012-03-12T12:11:12 +-- !sql_second_floor_TimestampNs_Integer -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:06.000000000 +2012-03-08 08:07:04.000000000 +2012-03-09 09:08:06.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:09.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_second_floor_DateTimeV2_Integer_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -501,6 +719,20 @@ 2012-03-11T11:10:09 2012-03-12T12:11:12 +-- !sql_second_floor_TimestampNs_Integer_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:06.000000000 +2012-03-08 08:07:04.000000000 +2012-03-09 09:08:06.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:09.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_second_floor_DateTime_Integer_DateTime -- \N 2012-03-01T01:00:01 @@ -545,6 +777,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_second_floor_TimestampNs_Integer_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_second_floor_DateTimeV2_Integer_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -559,6 +806,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_second_floor_TimestampNs_Integer_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_seconds_add_DateTime_Integer -- \N 2012-03-01T01:00:02 @@ -603,6 +864,21 @@ 2012-03-11T11:10:22 2012-03-12T12:11:24 +-- !sql_seconds_add_TimestampNs_Integer -- +\N +2012-03-01 01:00:02.000000000 +2012-03-02 02:01:04.000000000 +2012-03-03 03:02:06.000000000 +2012-03-04 04:03:08.000000000 +2012-03-05 05:04:10.000000000 +2012-03-06 06:05:12.000000000 +2012-03-07 07:06:14.000000000 +2012-03-08 08:07:16.000000000 +2012-03-09 09:08:18.000000000 +2012-03-10 10:09:20.000000000 +2012-03-11 11:10:22.000000000 +2012-03-12 12:11:24.000000000 + -- !sql_seconds_add_DateTimeV2_Integer_notnull -- 2012-03-01T01:00:02 2012-03-02T02:01:04 @@ -617,6 +893,20 @@ 2012-03-11T11:10:22 2012-03-12T12:11:24 +-- !sql_seconds_add_TimestampNs_Integer_notnull -- +2012-03-01 01:00:02.000000000 +2012-03-02 02:01:04.000000000 +2012-03-03 03:02:06.000000000 +2012-03-04 04:03:08.000000000 +2012-03-05 05:04:10.000000000 +2012-03-06 06:05:12.000000000 +2012-03-07 07:06:14.000000000 +2012-03-08 08:07:16.000000000 +2012-03-09 09:08:18.000000000 +2012-03-10 10:09:20.000000000 +2012-03-11 11:10:22.000000000 +2012-03-12 12:11:24.000000000 + -- !sql_seconds_add_Date_Integer -- \N 2012-03-01T00:00:01 @@ -719,6 +1009,21 @@ 0 0 +-- !sql_seconds_diff_TimestampNs_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_seconds_diff_DateTimeV2_DateTimeV2_notnull -- 0 0 @@ -733,6 +1038,20 @@ 0 0 +-- !sql_seconds_diff_TimestampNs_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_seconds_diff_DateV2_DateTimeV2 -- \N -3601 @@ -748,6 +1067,21 @@ -40211 -43872 +-- !sql_seconds_diff_DateV2_TimestampNs -- +\N +-3601 +-7262 +-10923 +-14584 +-18245 +-21906 +-25567 +-29228 +-32889 +-36550 +-40211 +-43872 + -- !sql_seconds_diff_DateV2_DateTimeV2_notnull -- -3601 -7262 @@ -762,6 +1096,20 @@ -40211 -43872 +-- !sql_seconds_diff_DateV2_TimestampNs_notnull -- +-3601 +-7262 +-10923 +-14584 +-18245 +-21906 +-25567 +-29228 +-32889 +-36550 +-40211 +-43872 + -- !sql_seconds_diff_DateTimeV2_DateV2 -- \N 3601 @@ -777,6 +1125,21 @@ 40211 43872 +-- !sql_seconds_diff_TimestampNs_DateV2 -- +\N +3601 +7262 +10923 +14584 +18245 +21906 +25567 +29228 +32889 +36550 +40211 +43872 + -- !sql_seconds_diff_DateTimeV2_DateV2_notnull -- 3601 7262 @@ -791,6 +1154,20 @@ 40211 43872 +-- !sql_seconds_diff_TimestampNs_DateV2_notnull -- +3601 +7262 +10923 +14584 +18245 +21906 +25567 +29228 +32889 +36550 +40211 +43872 + -- !sql_seconds_diff_DateV2_DateV2 -- \N 0 @@ -893,6 +1270,21 @@ 0 0 +-- !sql_seconds_diff_TimestampNs_DateTime -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_seconds_diff_DateTimeV2_DateTime_notnull -- 0 0 @@ -907,6 +1299,20 @@ 0 0 +-- !sql_seconds_diff_TimestampNs_DateTime_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_seconds_diff_DateTime_DateTimeV2 -- \N 0 @@ -922,6 +1328,21 @@ 0 0 +-- !sql_seconds_diff_DateTime_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_seconds_diff_DateTime_DateTimeV2_notnull -- 0 0 @@ -936,6 +1357,20 @@ 0 0 +-- !sql_seconds_diff_DateTime_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_sign_Double -- \N 1 diff --git a/regression-test/data/nereids_function_p0/scalar_function/T.out b/regression-test/data/nereids_function_p0/scalar_function/T.out index d293ed580a6a8c..0ff2a5f994a573 100644 --- a/regression-test/data/nereids_function_p0/scalar_function/T.out +++ b/regression-test/data/nereids_function_p0/scalar_function/T.out @@ -101,6 +101,21 @@ 00:00:00 00:00:00 +-- !sql_timediff_TimestampNs_TimestampNs -- +\N +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 + -- !sql_timediff_DateTimeV2_DateTimeV2_notnull -- 00:00:00 00:00:00 @@ -115,6 +130,20 @@ 00:00:00 00:00:00 +-- !sql_timediff_TimestampNs_TimestampNs_notnull -- +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 + -- !sql_timediff_DateTimeV2_DateV2 -- \N 01:00:01 @@ -130,6 +159,21 @@ 11:10:11 12:11:12 +-- !sql_timediff_TimestampNs_DateV2 -- +\N +01:00:01.000000 +02:01:02.000000 +03:02:03.000000 +04:03:04.000000 +05:04:05.000000 +06:05:06.000000 +07:06:07.000000 +08:07:08.000000 +09:08:09.000000 +10:09:10.000000 +11:10:11.000000 +12:11:12.000000 + -- !sql_timediff_DateTimeV2_DateV2_notnull -- 01:00:01 02:01:02 @@ -144,6 +188,20 @@ 11:10:11 12:11:12 +-- !sql_timediff_TimestampNs_DateV2_notnull -- +01:00:01.000000 +02:01:02.000000 +03:02:03.000000 +04:03:04.000000 +05:04:05.000000 +06:05:06.000000 +07:06:07.000000 +08:07:08.000000 +09:08:09.000000 +10:09:10.000000 +11:10:11.000000 +12:11:12.000000 + -- !sql_timediff_DateV2_DateTimeV2 -- \N -01:00:01 @@ -159,6 +217,21 @@ -11:10:11 -12:11:12 +-- !sql_timediff_DateV2_TimestampNs -- +\N +-01:00:01.000000 +-02:01:02.000000 +-03:02:03.000000 +-04:03:04.000000 +-05:04:05.000000 +-06:05:06.000000 +-07:06:07.000000 +-08:07:08.000000 +-09:08:09.000000 +-10:09:10.000000 +-11:10:11.000000 +-12:11:12.000000 + -- !sql_timediff_DateV2_DateTimeV2_notnull -- -01:00:01 -02:01:02 @@ -173,6 +246,20 @@ -11:10:11 -12:11:12 +-- !sql_timediff_DateV2_TimestampNs_notnull -- +-01:00:01.000000 +-02:01:02.000000 +-03:02:03.000000 +-04:03:04.000000 +-05:04:05.000000 +-06:05:06.000000 +-07:06:07.000000 +-08:07:08.000000 +-09:08:09.000000 +-10:09:10.000000 +-11:10:11.000000 +-12:11:12.000000 + -- !sql_timediff_DateV2_DateV2 -- \N 00:00:00 @@ -217,6 +304,21 @@ 00:00:00 00:00:00 +-- !sql_timediff_TimestampNs_DateTime -- +\N +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 + -- !sql_timediff_DateTimeV2_DateTime_notnull -- 00:00:00 00:00:00 @@ -231,6 +333,20 @@ 00:00:00 00:00:00 +-- !sql_timediff_TimestampNs_DateTime_notnull -- +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 +00:00:00.000000 + -- !sql_timediff_DateV2_DateTime -- \N -01:00:01 @@ -275,6 +391,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_timestamp_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_timestamp_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -289,6 +420,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_timestamp_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_timestamp_DateTime -- \N 2012-03-01T01:00:01 @@ -536,6 +681,21 @@ c3RyaW5nMw== 2012-03-11 2012-03-12 +-- !sql_to_date_TimestampNs -- +\N +2012-03-01 +2012-03-02 +2012-03-03 +2012-03-04 +2012-03-05 +2012-03-06 +2012-03-07 +2012-03-08 +2012-03-09 +2012-03-10 +2012-03-11 +2012-03-12 + -- !sql_to_date_DateTimeV2_notnull -- 2012-03-01 2012-03-02 @@ -550,6 +710,20 @@ c3RyaW5nMw== 2012-03-11 2012-03-12 +-- !sql_to_date_TimestampNs_notnull -- +2012-03-01 +2012-03-02 +2012-03-03 +2012-03-04 +2012-03-05 +2012-03-06 +2012-03-07 +2012-03-08 +2012-03-09 +2012-03-10 +2012-03-11 +2012-03-12 + -- !sql_to_datev2_DateTimeV2 -- \N 2012-03-01 @@ -565,6 +739,21 @@ c3RyaW5nMw== 2012-03-11 2012-03-12 +-- !sql_to_datev2_TimestampNs -- +\N +2012-03-01 +2012-03-02 +2012-03-03 +2012-03-04 +2012-03-05 +2012-03-06 +2012-03-07 +2012-03-08 +2012-03-09 +2012-03-10 +2012-03-11 +2012-03-12 + -- !sql_to_datev2_DateTimeV2_notnull -- 2012-03-01 2012-03-02 @@ -579,6 +768,20 @@ c3RyaW5nMw== 2012-03-11 2012-03-12 +-- !sql_to_datev2_TimestampNs_notnull -- +2012-03-01 +2012-03-02 +2012-03-03 +2012-03-04 +2012-03-05 +2012-03-06 +2012-03-07 +2012-03-08 +2012-03-09 +2012-03-10 +2012-03-11 +2012-03-12 + -- !sql_to_days_Date -- \N 734928 @@ -652,6 +855,21 @@ c3RyaW5nMw== 2012-03-05 2012-03-12 +-- !sql_to_monday_TimestampNs -- +\N +2012-02-27 +2012-02-27 +2012-02-27 +2012-02-27 +2012-03-05 +2012-03-05 +2012-03-05 +2012-03-05 +2012-03-05 +2012-03-05 +2012-03-05 +2012-03-12 + -- !sql_to_monday_DateTimeV2_notnull -- 2012-02-27 2012-02-27 @@ -666,6 +884,20 @@ c3RyaW5nMw== 2012-03-05 2012-03-12 +-- !sql_to_monday_TimestampNs_notnull -- +2012-02-27 +2012-02-27 +2012-02-27 +2012-02-27 +2012-03-05 +2012-03-05 +2012-03-05 +2012-03-05 +2012-03-05 +2012-03-05 +2012-03-05 +2012-03-12 + -- !sql_to_monday_DateV2 -- \N 2012-02-27 diff --git a/regression-test/data/nereids_function_p0/scalar_function/U.out b/regression-test/data/nereids_function_p0/scalar_function/U.out index 0e251ea152f084..6d46cb9414571d 100644 --- a/regression-test/data/nereids_function_p0/scalar_function/U.out +++ b/regression-test/data/nereids_function_p0/scalar_function/U.out @@ -130,6 +130,21 @@ 1331435411 1331525472 +-- !sql_unix_timestamp_TimestampNs -- +\N +1330534801.000000000 +1330624862.000000000 +1330714923.000000000 +1330804984.000000000 +1330895045.000000000 +1330985106.000000000 +1331075167.000000000 +1331165228.000000000 +1331255289.000000000 +1331345350.000000000 +1331435411.000000000 +1331525472.000000000 + -- !sql_unix_timestamp_DateTimeV2_notnull -- 1330534801 1330624862 @@ -144,6 +159,20 @@ 1331435411 1331525472 +-- !sql_unix_timestamp_TimestampNs_notnull -- +1330534801.000000000 +1330624862.000000000 +1330714923.000000000 +1330804984.000000000 +1330895045.000000000 +1330985106.000000000 +1331075167.000000000 +1331165228.000000000 +1331255289.000000000 +1331345350.000000000 +1331435411.000000000 +1331525472.000000000 + -- !sql_unix_timestamp_DateV2 -- \N 1330531200 diff --git a/regression-test/data/nereids_function_p0/scalar_function/W.out b/regression-test/data/nereids_function_p0/scalar_function/W.out index 89901daad5c7eb..aa739a16570d1d 100644 --- a/regression-test/data/nereids_function_p0/scalar_function/W.out +++ b/regression-test/data/nereids_function_p0/scalar_function/W.out @@ -43,6 +43,21 @@ 11 11 +-- !sql_week_TimestampNs -- +\N +9 +9 +9 +10 +10 +10 +10 +10 +10 +10 +11 +11 + -- !sql_week_DateTimeV2_notnull -- 9 9 @@ -57,6 +72,20 @@ 11 11 +-- !sql_week_TimestampNs_notnull -- +9 +9 +9 +10 +10 +10 +10 +10 +10 +10 +11 +11 + -- !sql_week_DateV2 -- \N 9 @@ -130,6 +159,21 @@ 10 11 +-- !sql_week_TimestampNs_Integer -- +\N +9 +9 +9 +10 +10 +10 +10 +10 +10 +10 +10 +11 + -- !sql_week_DateTimeV2_Integer_notnull -- 9 9 @@ -144,6 +188,20 @@ 10 11 +-- !sql_week_TimestampNs_Integer_notnull -- +9 +9 +9 +10 +10 +10 +10 +10 +10 +10 +10 +11 + -- !sql_week_DateV2_Integer -- \N 9 @@ -217,6 +275,21 @@ 2012-03-12T00:00 2012-03-19T00:00 +-- !sql_week_ceil_TimestampNs -- +\N +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-12 00:00:00.000000000 +2012-03-12 00:00:00.000000000 +2012-03-12 00:00:00.000000000 +2012-03-12 00:00:00.000000000 +2012-03-12 00:00:00.000000000 +2012-03-12 00:00:00.000000000 +2012-03-12 00:00:00.000000000 +2012-03-19 00:00:00.000000000 + -- !sql_week_ceil_DateTimeV2_notnull -- 2012-03-05T00:00 2012-03-05T00:00 @@ -231,6 +304,20 @@ 2012-03-12T00:00 2012-03-19T00:00 +-- !sql_week_ceil_TimestampNs_notnull -- +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-12 00:00:00.000000000 +2012-03-12 00:00:00.000000000 +2012-03-12 00:00:00.000000000 +2012-03-12 00:00:00.000000000 +2012-03-12 00:00:00.000000000 +2012-03-12 00:00:00.000000000 +2012-03-12 00:00:00.000000000 +2012-03-19 00:00:00.000000000 + -- !sql_week_ceil_DateV2 -- \N 2012-03-05 @@ -333,6 +420,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_week_ceil_TimestampNs_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_week_ceil_DateTimeV2_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -347,6 +449,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_week_ceil_TimestampNs_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_week_ceil_DateTimeV2_Integer -- \N 2012-03-05T00:00 @@ -362,6 +478,21 @@ 2012-03-19T00:00 2012-03-19T00:00 +-- !sql_week_ceil_TimestampNs_Integer -- +\N +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-19 00:00:00.000000000 +2012-03-19 00:00:00.000000000 +2012-03-19 00:00:00.000000000 +2012-03-19 00:00:00.000000000 +2012-04-16 00:00:00.000000000 +2012-04-16 00:00:00.000000000 +2012-03-19 00:00:00.000000000 +2012-03-19 00:00:00.000000000 +2012-03-19 00:00:00.000000000 +2012-03-19 00:00:00.000000000 + -- !sql_week_ceil_DateTimeV2_Integer_notnull -- 2012-03-05T00:00 2012-03-05T00:00 @@ -376,6 +507,20 @@ 2012-03-19T00:00 2012-03-19T00:00 +-- !sql_week_ceil_TimestampNs_Integer_notnull -- +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-19 00:00:00.000000000 +2012-03-19 00:00:00.000000000 +2012-03-19 00:00:00.000000000 +2012-03-19 00:00:00.000000000 +2012-04-16 00:00:00.000000000 +2012-04-16 00:00:00.000000000 +2012-03-19 00:00:00.000000000 +2012-03-19 00:00:00.000000000 +2012-03-19 00:00:00.000000000 +2012-03-19 00:00:00.000000000 + -- !sql_week_ceil_DateV2_DateV2 -- \N 2012-03-01 @@ -478,6 +623,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_week_ceil_TimestampNs_Integer_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_week_ceil_DateTimeV2_Integer_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -492,6 +652,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_week_ceil_TimestampNs_Integer_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_week_ceil_DateV2_Integer_DateV2 -- \N 2012-03-01 @@ -565,6 +739,21 @@ 2012-03-05T00:00 2012-03-12T00:00 +-- !sql_week_floor_TimestampNs -- +\N +2012-02-27 00:00:00.000000000 +2012-02-27 00:00:00.000000000 +2012-02-27 00:00:00.000000000 +2012-02-27 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-12 00:00:00.000000000 + -- !sql_week_floor_DateTimeV2_notnull -- 2012-02-27T00:00 2012-02-27T00:00 @@ -579,6 +768,20 @@ 2012-03-05T00:00 2012-03-12T00:00 +-- !sql_week_floor_TimestampNs_notnull -- +2012-02-27 00:00:00.000000000 +2012-02-27 00:00:00.000000000 +2012-02-27 00:00:00.000000000 +2012-02-27 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-05 00:00:00.000000000 +2012-03-12 00:00:00.000000000 + -- !sql_week_floor_DateV2 -- \N 2012-02-27 @@ -681,6 +884,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_week_floor_TimestampNs_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_week_floor_DateTimeV2_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -695,6 +913,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_week_floor_TimestampNs_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_week_floor_DateTimeV2_Integer -- \N 2012-02-27T00:00 @@ -710,6 +942,21 @@ 2012-01-02T00:00 2011-12-26T00:00 +-- !sql_week_floor_TimestampNs_Integer -- +\N +2012-02-27 00:00:00.000000000 +2012-02-20 00:00:00.000000000 +2012-02-27 00:00:00.000000000 +2012-02-20 00:00:00.000000000 +2012-02-13 00:00:00.000000000 +2012-02-06 00:00:00.000000000 +2012-02-27 00:00:00.000000000 +2012-02-20 00:00:00.000000000 +2012-01-16 00:00:00.000000000 +2012-01-09 00:00:00.000000000 +2012-01-02 00:00:00.000000000 +2011-12-26 00:00:00.000000000 + -- !sql_week_floor_DateTimeV2_Integer_notnull -- 2012-02-27T00:00 2012-02-20T00:00 @@ -724,6 +971,20 @@ 2012-01-02T00:00 2011-12-26T00:00 +-- !sql_week_floor_TimestampNs_Integer_notnull -- +2012-02-27 00:00:00.000000000 +2012-02-20 00:00:00.000000000 +2012-02-27 00:00:00.000000000 +2012-02-20 00:00:00.000000000 +2012-02-13 00:00:00.000000000 +2012-02-06 00:00:00.000000000 +2012-02-27 00:00:00.000000000 +2012-02-20 00:00:00.000000000 +2012-01-16 00:00:00.000000000 +2012-01-09 00:00:00.000000000 +2012-01-02 00:00:00.000000000 +2011-12-26 00:00:00.000000000 + -- !sql_week_floor_DateV2_DateV2 -- \N 2012-03-01 @@ -826,6 +1087,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_week_floor_TimestampNs_Integer_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_week_floor_DateTimeV2_Integer_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -840,6 +1116,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_week_floor_TimestampNs_Integer_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_week_floor_DateV2_Integer_DateV2 -- \N 2012-03-01 @@ -913,6 +1203,21 @@ 6 0 +-- !sql_weekday_TimestampNs -- +\N +3 +4 +5 +6 +0 +1 +2 +3 +4 +5 +6 +0 + -- !sql_weekday_DateTimeV2_notnull -- 3 4 @@ -927,6 +1232,20 @@ 6 0 +-- !sql_weekday_TimestampNs_notnull -- +3 +4 +5 +6 +0 +1 +2 +3 +4 +5 +6 +0 + -- !sql_weekday_DateV2 -- \N 3 @@ -1000,6 +1319,21 @@ 10 11 +-- !sql_weekofyear_TimestampNs -- +\N +9 +9 +9 +9 +10 +10 +10 +10 +10 +10 +10 +11 + -- !sql_weekofyear_DateTimeV2_notnull -- 9 9 @@ -1014,6 +1348,20 @@ 10 11 +-- !sql_weekofyear_TimestampNs_notnull -- +9 +9 +9 +9 +10 +10 +10 +10 +10 +10 +10 +11 + -- !sql_weekofyear_DateV2 -- \N 9 @@ -1058,6 +1406,21 @@ 2012-05-27T11:10:11 2012-06-04T12:11:12 +-- !sql_weeks_add_TimestampNs_Integer -- +\N +2012-03-08 01:00:01.000000000 +2012-03-16 02:01:02.000000000 +2012-03-24 03:02:03.000000000 +2012-04-01 04:03:04.000000000 +2012-04-09 05:04:05.000000000 +2012-04-17 06:05:06.000000000 +2012-04-25 07:06:07.000000000 +2012-05-03 08:07:08.000000000 +2012-05-11 09:08:09.000000000 +2012-05-19 10:09:10.000000000 +2012-05-27 11:10:11.000000000 +2012-06-04 12:11:12.000000000 + -- !sql_weeks_add_DateTimeV2_Integer_notnull -- 2012-03-08T01:00:01 2012-03-16T02:01:02 @@ -1072,6 +1435,20 @@ 2012-05-27T11:10:11 2012-06-04T12:11:12 +-- !sql_weeks_add_TimestampNs_Integer_notnull -- +2012-03-08 01:00:01.000000000 +2012-03-16 02:01:02.000000000 +2012-03-24 03:02:03.000000000 +2012-04-01 04:03:04.000000000 +2012-04-09 05:04:05.000000000 +2012-04-17 06:05:06.000000000 +2012-04-25 07:06:07.000000000 +2012-05-03 08:07:08.000000000 +2012-05-11 09:08:09.000000000 +2012-05-19 10:09:10.000000000 +2012-05-27 11:10:11.000000000 +2012-06-04 12:11:12.000000000 + -- !sql_weeks_add_DateV2_Integer -- \N 2012-03-08 @@ -1319,6 +1696,21 @@ 0 0 +-- !sql_weeks_diff_TimestampNs_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_weeks_diff_DateTimeV2_DateTimeV2_notnull -- 0 0 @@ -1333,6 +1725,20 @@ 0 0 +-- !sql_weeks_diff_TimestampNs_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_weeks_diff_DateV2_DateTimeV2 -- \N 0 @@ -1348,6 +1754,21 @@ 0 0 +-- !sql_weeks_diff_DateV2_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_weeks_diff_DateV2_DateTimeV2_notnull -- 0 0 @@ -1362,6 +1783,20 @@ 0 0 +-- !sql_weeks_diff_DateV2_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_weeks_diff_DateTimeV2_DateV2 -- \N 0 @@ -1377,6 +1812,21 @@ 0 0 +-- !sql_weeks_diff_TimestampNs_DateV2 -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_weeks_diff_DateTimeV2_DateV2_notnull -- 0 0 @@ -1391,6 +1841,20 @@ 0 0 +-- !sql_weeks_diff_TimestampNs_DateV2_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_weeks_diff_DateV2_DateV2 -- \N 0 @@ -1493,6 +1957,21 @@ 0 0 +-- !sql_weeks_diff_TimestampNs_DateTime -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_weeks_diff_DateTimeV2_DateTime_notnull -- 0 0 @@ -1507,6 +1986,20 @@ 0 0 +-- !sql_weeks_diff_TimestampNs_DateTime_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_weeks_diff_DateTime_DateTimeV2 -- \N 0 @@ -1522,6 +2015,21 @@ 0 0 +-- !sql_weeks_diff_DateTime_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_weeks_diff_DateTime_DateTimeV2_notnull -- 0 0 @@ -1536,6 +2044,20 @@ 0 0 +-- !sql_weeks_diff_DateTime_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_weeks_sub_DateTimeV2_Integer -- \N 2012-02-23T01:00:01 @@ -1551,6 +2073,21 @@ 2011-12-25T11:10:11 2011-12-19T12:11:12 +-- !sql_weeks_sub_TimestampNs_Integer -- +\N +2012-02-23 01:00:01.000000000 +2012-02-17 02:01:02.000000000 +2012-02-11 03:02:03.000000000 +2012-02-05 04:03:04.000000000 +2012-01-30 05:04:05.000000000 +2012-01-24 06:05:06.000000000 +2012-01-18 07:06:07.000000000 +2012-01-12 08:07:08.000000000 +2012-01-06 09:08:09.000000000 +2011-12-31 10:09:10.000000000 +2011-12-25 11:10:11.000000000 +2011-12-19 12:11:12.000000000 + -- !sql_weeks_sub_DateTimeV2_Integer_notnull -- 2012-02-23T01:00:01 2012-02-17T02:01:02 @@ -1565,6 +2102,20 @@ 2011-12-25T11:10:11 2011-12-19T12:11:12 +-- !sql_weeks_sub_TimestampNs_Integer_notnull -- +2012-02-23 01:00:01.000000000 +2012-02-17 02:01:02.000000000 +2012-02-11 03:02:03.000000000 +2012-02-05 04:03:04.000000000 +2012-01-30 05:04:05.000000000 +2012-01-24 06:05:06.000000000 +2012-01-18 07:06:07.000000000 +2012-01-12 08:07:08.000000000 +2012-01-06 09:08:09.000000000 +2011-12-31 10:09:10.000000000 +2011-12-25 11:10:11.000000000 +2011-12-19 12:11:12.000000000 + -- !sql_weeks_sub_DateV2_Integer -- \N 2012-02-23 @@ -2073,6 +2624,21 @@ 1 1 +-- !sql_width_bucket_TimestampNs_TimestampNs_TimestampNs_TinyInt -- +\N +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 + -- !sql_width_bucket_DateTimeV2_DateTimeV2_DateTimeV2_TinyInt_notnull -- 1 1 @@ -2087,3 +2653,17 @@ 1 1 +-- !sql_width_bucket_TimestampNs_TimestampNs_TimestampNs_TinyInt_notnull -- +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 + diff --git a/regression-test/data/nereids_function_p0/scalar_function/Y.out b/regression-test/data/nereids_function_p0/scalar_function/Y.out index 0e0fb57cdf6029..31e71d56e4bd5e 100644 --- a/regression-test/data/nereids_function_p0/scalar_function/Y.out +++ b/regression-test/data/nereids_function_p0/scalar_function/Y.out @@ -72,6 +72,21 @@ 2012 2012 +-- !sql_year_TimestampNs -- +\N +2012 +2012 +2012 +2012 +2012 +2012 +2012 +2012 +2012 +2012 +2012 +2012 + -- !sql_year_DateTimeV2_notnull -- 2012 2012 @@ -86,6 +101,20 @@ 2012 2012 +-- !sql_year_TimestampNs_notnull -- +2012 +2012 +2012 +2012 +2012 +2012 +2012 +2012 +2012 +2012 +2012 +2012 + -- !sql_year_ceil_DateTime -- \N 2013-01-01T00:00 @@ -130,6 +159,21 @@ 2013-01-01T00:00 2013-01-01T00:00 +-- !sql_year_ceil_TimestampNs -- +\N +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 + -- !sql_year_ceil_DateTimeV2_notnull -- 2013-01-01T00:00 2013-01-01T00:00 @@ -144,6 +188,20 @@ 2013-01-01T00:00 2013-01-01T00:00 +-- !sql_year_ceil_TimestampNs_notnull -- +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 + -- !sql_year_ceil_DateV2 -- \N 2013-01-01 @@ -246,6 +304,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_year_ceil_TimestampNs_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_year_ceil_DateTimeV2_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -260,6 +333,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_year_ceil_TimestampNs_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_year_ceil_DateTimeV2_Integer -- \N 2013-01-01T00:00 @@ -275,6 +362,21 @@ 2014-01-01T00:00 2017-01-01T00:00 +-- !sql_year_ceil_TimestampNs_Integer -- +\N +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2014-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2016-01-01 00:00:00.000000000 +2017-01-01 00:00:00.000000000 +2017-01-01 00:00:00.000000000 +2017-01-01 00:00:00.000000000 +2017-01-01 00:00:00.000000000 +2021-01-01 00:00:00.000000000 +2014-01-01 00:00:00.000000000 +2017-01-01 00:00:00.000000000 + -- !sql_year_ceil_DateTimeV2_Integer_notnull -- 2013-01-01T00:00 2013-01-01T00:00 @@ -289,6 +391,20 @@ 2014-01-01T00:00 2017-01-01T00:00 +-- !sql_year_ceil_TimestampNs_Integer_notnull -- +2013-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2014-01-01 00:00:00.000000000 +2013-01-01 00:00:00.000000000 +2016-01-01 00:00:00.000000000 +2017-01-01 00:00:00.000000000 +2017-01-01 00:00:00.000000000 +2017-01-01 00:00:00.000000000 +2017-01-01 00:00:00.000000000 +2021-01-01 00:00:00.000000000 +2014-01-01 00:00:00.000000000 +2017-01-01 00:00:00.000000000 + -- !sql_year_ceil_DateV2_DateV2 -- \N 2012-03-01 @@ -391,6 +507,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_year_ceil_TimestampNs_Integer_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_year_ceil_DateTimeV2_Integer_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -405,6 +536,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_year_ceil_TimestampNs_Integer_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_year_ceil_DateV2_Integer_DateV2 -- \N 2012-03-01 @@ -478,6 +623,21 @@ 2012-01-01T00:00 2012-01-01T00:00 +-- !sql_year_floor_TimestampNs -- +\N +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 + -- !sql_year_floor_DateTimeV2_notnull -- 2012-01-01T00:00 2012-01-01T00:00 @@ -492,6 +652,20 @@ 2012-01-01T00:00 2012-01-01T00:00 +-- !sql_year_floor_TimestampNs_notnull -- +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 +2012-01-01 00:00:00.000000000 + -- !sql_year_floor_DateV2 -- \N 2012-01-01 @@ -594,6 +768,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_year_floor_TimestampNs_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_year_floor_DateTimeV2_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -608,6 +797,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_year_floor_TimestampNs_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_year_floor_DateTimeV2_Integer -- \N 2012-01-01T00:00 @@ -623,6 +826,21 @@ 2003-01-01T00:00 2005-01-01T00:00 +-- !sql_year_floor_TimestampNs_Integer -- +\N +2012-01-01 00:00:00.000000000 +2011-01-01 00:00:00.000000000 +2011-01-01 00:00:00.000000000 +2009-01-01 00:00:00.000000000 +2011-01-01 00:00:00.000000000 +2011-01-01 00:00:00.000000000 +2010-01-01 00:00:00.000000000 +2009-01-01 00:00:00.000000000 +2008-01-01 00:00:00.000000000 +2011-01-01 00:00:00.000000000 +2003-01-01 00:00:00.000000000 +2005-01-01 00:00:00.000000000 + -- !sql_year_floor_DateTimeV2_Integer_notnull -- 2012-01-01T00:00 2011-01-01T00:00 @@ -637,6 +855,20 @@ 2003-01-01T00:00 2005-01-01T00:00 +-- !sql_year_floor_TimestampNs_Integer_notnull -- +2012-01-01 00:00:00.000000000 +2011-01-01 00:00:00.000000000 +2011-01-01 00:00:00.000000000 +2009-01-01 00:00:00.000000000 +2011-01-01 00:00:00.000000000 +2011-01-01 00:00:00.000000000 +2010-01-01 00:00:00.000000000 +2009-01-01 00:00:00.000000000 +2008-01-01 00:00:00.000000000 +2011-01-01 00:00:00.000000000 +2003-01-01 00:00:00.000000000 +2005-01-01 00:00:00.000000000 + -- !sql_year_floor_DateV2_DateV2 -- \N 2012-03-01 @@ -739,6 +971,21 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_year_floor_TimestampNs_Integer_TimestampNs -- +\N +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_year_floor_DateTimeV2_Integer_DateTimeV2_notnull -- 2012-03-01T01:00:01 2012-03-02T02:01:02 @@ -753,6 +1000,20 @@ 2012-03-11T11:10:11 2012-03-12T12:11:12 +-- !sql_year_floor_TimestampNs_Integer_TimestampNs_notnull -- +2012-03-01 01:00:01.000000000 +2012-03-02 02:01:02.000000000 +2012-03-03 03:02:03.000000000 +2012-03-04 04:03:04.000000000 +2012-03-05 05:04:05.000000000 +2012-03-06 06:05:06.000000000 +2012-03-07 07:06:07.000000000 +2012-03-08 08:07:08.000000000 +2012-03-09 09:08:09.000000000 +2012-03-10 10:09:10.000000000 +2012-03-11 11:10:11.000000000 +2012-03-12 12:11:12.000000000 + -- !sql_year_floor_DateV2_Integer_DateV2 -- \N 2012-03-01 @@ -826,6 +1087,21 @@ 2023-03-11T11:10:11 2024-03-12T12:11:12 +-- !sql_years_add_TimestampNs_Integer -- +\N +2013-03-01 01:00:01.000000000 +2014-03-02 02:01:02.000000000 +2015-03-03 03:02:03.000000000 +2016-03-04 04:03:04.000000000 +2017-03-05 05:04:05.000000000 +2018-03-06 06:05:06.000000000 +2019-03-07 07:06:07.000000000 +2020-03-08 08:07:08.000000000 +2021-03-09 09:08:09.000000000 +2022-03-10 10:09:10.000000000 +2023-03-11 11:10:11.000000000 +2024-03-12 12:11:12.000000000 + -- !sql_years_add_DateTimeV2_Integer_notnull -- 2013-03-01T01:00:01 2014-03-02T02:01:02 @@ -840,6 +1116,20 @@ 2023-03-11T11:10:11 2024-03-12T12:11:12 +-- !sql_years_add_TimestampNs_Integer_notnull -- +2013-03-01 01:00:01.000000000 +2014-03-02 02:01:02.000000000 +2015-03-03 03:02:03.000000000 +2016-03-04 04:03:04.000000000 +2017-03-05 05:04:05.000000000 +2018-03-06 06:05:06.000000000 +2019-03-07 07:06:07.000000000 +2020-03-08 08:07:08.000000000 +2021-03-09 09:08:09.000000000 +2022-03-10 10:09:10.000000000 +2023-03-11 11:10:11.000000000 +2024-03-12 12:11:12.000000000 + -- !sql_years_add_Date_Integer -- \N 2013-03-01 @@ -942,6 +1232,21 @@ 0 0 +-- !sql_years_diff_TimestampNs_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_years_diff_DateTimeV2_DateTimeV2_notnull -- 0 0 @@ -956,6 +1261,20 @@ 0 0 +-- !sql_years_diff_TimestampNs_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_years_diff_DateV2_DateTimeV2 -- \N 0 @@ -971,6 +1290,21 @@ 0 0 +-- !sql_years_diff_DateV2_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_years_diff_DateV2_DateTimeV2_notnull -- 0 0 @@ -985,6 +1319,20 @@ 0 0 +-- !sql_years_diff_DateV2_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_years_diff_DateTimeV2_DateV2 -- \N 0 @@ -1000,6 +1348,21 @@ 0 0 +-- !sql_years_diff_TimestampNs_DateV2 -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_years_diff_DateTimeV2_DateV2_notnull -- 0 0 @@ -1014,6 +1377,20 @@ 0 0 +-- !sql_years_diff_TimestampNs_DateV2_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_years_diff_DateV2_DateV2 -- \N 0 @@ -1116,6 +1493,21 @@ 0 0 +-- !sql_years_diff_TimestampNs_DateTime -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_years_diff_DateTimeV2_DateTime_notnull -- 0 0 @@ -1130,6 +1522,20 @@ 0 0 +-- !sql_years_diff_TimestampNs_DateTime_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_years_diff_DateTime_DateTimeV2 -- \N 0 @@ -1145,6 +1551,21 @@ 0 0 +-- !sql_years_diff_DateTime_TimestampNs -- +\N +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_years_diff_DateTime_DateTimeV2_notnull -- 0 0 @@ -1159,6 +1580,20 @@ 0 0 +-- !sql_years_diff_DateTime_TimestampNs_notnull -- +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + -- !sql_years_sub_DateTime_Integer -- \N 2011-03-01T01:00:01 @@ -1203,6 +1638,21 @@ 2001-03-11T11:10:11 2000-03-12T12:11:12 +-- !sql_years_sub_TimestampNs_Integer -- +\N +2011-03-01 01:00:01.000000000 +2010-03-02 02:01:02.000000000 +2009-03-03 03:02:03.000000000 +2008-03-04 04:03:04.000000000 +2007-03-05 05:04:05.000000000 +2006-03-06 06:05:06.000000000 +2005-03-07 07:06:07.000000000 +2004-03-08 08:07:08.000000000 +2003-03-09 09:08:09.000000000 +2002-03-10 10:09:10.000000000 +2001-03-11 11:10:11.000000000 +2000-03-12 12:11:12.000000000 + -- !sql_years_sub_DateTimeV2_Integer_notnull -- 2011-03-01T01:00:01 2010-03-02T02:01:02 @@ -1217,6 +1667,20 @@ 2001-03-11T11:10:11 2000-03-12T12:11:12 +-- !sql_years_sub_TimestampNs_Integer_notnull -- +2011-03-01 01:00:01.000000000 +2010-03-02 02:01:02.000000000 +2009-03-03 03:02:03.000000000 +2008-03-04 04:03:04.000000000 +2007-03-05 05:04:05.000000000 +2006-03-06 06:05:06.000000000 +2005-03-07 07:06:07.000000000 +2004-03-08 08:07:08.000000000 +2003-03-09 09:08:09.000000000 +2002-03-10 10:09:10.000000000 +2001-03-11 11:10:11.000000000 +2000-03-12 12:11:12.000000000 + -- !sql_years_sub_Date_Integer -- \N 2011-03-01 @@ -1319,6 +1783,21 @@ 201211 201211 +-- !sql_yearweek_TimestampNs -- +\N +201209 +201209 +201209 +201210 +201210 +201210 +201210 +201210 +201210 +201210 +201211 +201211 + -- !sql_yearweek_DateTimeV2_notnull -- 201209 201209 @@ -1333,6 +1812,20 @@ 201211 201211 +-- !sql_yearweek_TimestampNs_notnull -- +201209 +201209 +201209 +201210 +201210 +201210 +201210 +201210 +201210 +201210 +201211 +201211 + -- !sql_yearweek_DateV2 -- \N 201209 @@ -1406,6 +1899,21 @@ 201210 201211 +-- !sql_yearweek_TimestampNs_Integer -- +\N +201209 +201209 +201209 +201210 +201210 +201210 +201210 +201210 +201210 +201210 +201210 +201211 + -- !sql_yearweek_DateTimeV2_Integer_notnull -- 201209 201209 @@ -1420,6 +1928,20 @@ 201210 201211 +-- !sql_yearweek_TimestampNs_Integer_notnull -- +201209 +201209 +201209 +201210 +201210 +201210 +201210 +201210 +201210 +201210 +201210 +201211 + -- !sql_yearweek_DateV2_Integer -- \N 201209 diff --git a/regression-test/data/nereids_function_p0/test_timestamp_arithmetic.out b/regression-test/data/nereids_function_p0/test_timestamp_arithmetic.out index 979c29e2d6217b..042e4edab34542 100644 --- a/regression-test/data/nereids_function_p0/test_timestamp_arithmetic.out +++ b/regression-test/data/nereids_function_p0/test_timestamp_arithmetic.out @@ -2011,3 +2011,467 @@ 2012-03-11T11:10:10 2012-03-12T12:11:11 +-- !test_timestamp_arithmetic_141 -- +\N +2013-03-01 01:00:01.000000000 +2013-03-02 02:01:02.000000000 +2013-03-03 03:02:03.000000000 +2013-03-04 04:03:04.000000000 +2013-03-05 05:04:05.000000000 +2013-03-06 06:05:06.000000000 +2013-03-07 07:06:07.000000000 +2013-03-08 08:07:08.000000000 +2013-03-09 09:08:09.000000000 +2013-03-10 10:09:10.000000000 +2013-03-11 11:10:11.000000000 +2013-03-12 12:11:12.000000000 + +-- !test_timestamp_arithmetic_142 -- +\N +2012-04-01 01:00:01.000000000 +2012-04-02 02:01:02.000000000 +2012-04-03 03:02:03.000000000 +2012-04-04 04:03:04.000000000 +2012-04-05 05:04:05.000000000 +2012-04-06 06:05:06.000000000 +2012-04-07 07:06:07.000000000 +2012-04-08 08:07:08.000000000 +2012-04-09 09:08:09.000000000 +2012-04-10 10:09:10.000000000 +2012-04-11 11:10:11.000000000 +2012-04-12 12:11:12.000000000 + +-- !test_timestamp_arithmetic_143 -- +\N +2012-03-08 01:00:01.000000000 +2012-03-09 02:01:02.000000000 +2012-03-10 03:02:03.000000000 +2012-03-11 04:03:04.000000000 +2012-03-12 05:04:05.000000000 +2012-03-13 06:05:06.000000000 +2012-03-14 07:06:07.000000000 +2012-03-15 08:07:08.000000000 +2012-03-16 09:08:09.000000000 +2012-03-17 10:09:10.000000000 +2012-03-18 11:10:11.000000000 +2012-03-19 12:11:12.000000000 + +-- !test_timestamp_arithmetic_144 -- +\N +2012-03-02 01:00:01.000000000 +2012-03-03 02:01:02.000000000 +2012-03-04 03:02:03.000000000 +2012-03-05 04:03:04.000000000 +2012-03-06 05:04:05.000000000 +2012-03-07 06:05:06.000000000 +2012-03-08 07:06:07.000000000 +2012-03-09 08:07:08.000000000 +2012-03-10 09:08:09.000000000 +2012-03-11 10:09:10.000000000 +2012-03-12 11:10:11.000000000 +2012-03-13 12:11:12.000000000 + +-- !test_timestamp_arithmetic_145 -- +\N +2012-03-01 02:00:01.000000000 +2012-03-02 03:01:02.000000000 +2012-03-03 04:02:03.000000000 +2012-03-04 05:03:04.000000000 +2012-03-05 06:04:05.000000000 +2012-03-06 07:05:06.000000000 +2012-03-07 08:06:07.000000000 +2012-03-08 09:07:08.000000000 +2012-03-09 10:08:09.000000000 +2012-03-10 11:09:10.000000000 +2012-03-11 12:10:11.000000000 +2012-03-12 13:11:12.000000000 + +-- !test_timestamp_arithmetic_146 -- +\N +2012-03-01 01:01:01.000000000 +2012-03-02 02:02:02.000000000 +2012-03-03 03:03:03.000000000 +2012-03-04 04:04:04.000000000 +2012-03-05 05:05:05.000000000 +2012-03-06 06:06:06.000000000 +2012-03-07 07:07:07.000000000 +2012-03-08 08:08:08.000000000 +2012-03-09 09:09:09.000000000 +2012-03-10 10:10:10.000000000 +2012-03-11 11:11:11.000000000 +2012-03-12 12:12:12.000000000 + +-- !test_timestamp_arithmetic_147 -- +\N +2012-03-01 01:00:02.000000000 +2012-03-02 02:01:03.000000000 +2012-03-03 03:02:04.000000000 +2012-03-04 04:03:05.000000000 +2012-03-05 05:04:06.000000000 +2012-03-06 06:05:07.000000000 +2012-03-07 07:06:08.000000000 +2012-03-08 08:07:09.000000000 +2012-03-09 09:08:10.000000000 +2012-03-10 10:09:11.000000000 +2012-03-11 11:10:12.000000000 +2012-03-12 12:11:13.000000000 + +-- !test_timestamp_arithmetic_148 -- +\N +2013-03-01 01:00:01.000000000 +2013-03-02 02:01:02.000000000 +2013-03-03 03:02:03.000000000 +2013-03-04 04:03:04.000000000 +2013-03-05 05:04:05.000000000 +2013-03-06 06:05:06.000000000 +2013-03-07 07:06:07.000000000 +2013-03-08 08:07:08.000000000 +2013-03-09 09:08:09.000000000 +2013-03-10 10:09:10.000000000 +2013-03-11 11:10:11.000000000 +2013-03-12 12:11:12.000000000 + +-- !test_timestamp_arithmetic_149 -- +\N +2012-04-01 01:00:01.000000000 +2012-04-02 02:01:02.000000000 +2012-04-03 03:02:03.000000000 +2012-04-04 04:03:04.000000000 +2012-04-05 05:04:05.000000000 +2012-04-06 06:05:06.000000000 +2012-04-07 07:06:07.000000000 +2012-04-08 08:07:08.000000000 +2012-04-09 09:08:09.000000000 +2012-04-10 10:09:10.000000000 +2012-04-11 11:10:11.000000000 +2012-04-12 12:11:12.000000000 + +-- !test_timestamp_arithmetic_150 -- +\N +2012-03-08 01:00:01.000000000 +2012-03-09 02:01:02.000000000 +2012-03-10 03:02:03.000000000 +2012-03-11 04:03:04.000000000 +2012-03-12 05:04:05.000000000 +2012-03-13 06:05:06.000000000 +2012-03-14 07:06:07.000000000 +2012-03-15 08:07:08.000000000 +2012-03-16 09:08:09.000000000 +2012-03-17 10:09:10.000000000 +2012-03-18 11:10:11.000000000 +2012-03-19 12:11:12.000000000 + +-- !test_timestamp_arithmetic_151 -- +\N +2012-03-02 01:00:01.000000000 +2012-03-03 02:01:02.000000000 +2012-03-04 03:02:03.000000000 +2012-03-05 04:03:04.000000000 +2012-03-06 05:04:05.000000000 +2012-03-07 06:05:06.000000000 +2012-03-08 07:06:07.000000000 +2012-03-09 08:07:08.000000000 +2012-03-10 09:08:09.000000000 +2012-03-11 10:09:10.000000000 +2012-03-12 11:10:11.000000000 +2012-03-13 12:11:12.000000000 + +-- !test_timestamp_arithmetic_152 -- +\N +2012-03-01 02:00:01.000000000 +2012-03-02 03:01:02.000000000 +2012-03-03 04:02:03.000000000 +2012-03-04 05:03:04.000000000 +2012-03-05 06:04:05.000000000 +2012-03-06 07:05:06.000000000 +2012-03-07 08:06:07.000000000 +2012-03-08 09:07:08.000000000 +2012-03-09 10:08:09.000000000 +2012-03-10 11:09:10.000000000 +2012-03-11 12:10:11.000000000 +2012-03-12 13:11:12.000000000 + +-- !test_timestamp_arithmetic_153 -- +\N +2012-03-01 01:01:01.000000000 +2012-03-02 02:02:02.000000000 +2012-03-03 03:03:03.000000000 +2012-03-04 04:04:04.000000000 +2012-03-05 05:05:05.000000000 +2012-03-06 06:06:06.000000000 +2012-03-07 07:07:07.000000000 +2012-03-08 08:08:08.000000000 +2012-03-09 09:09:09.000000000 +2012-03-10 10:10:10.000000000 +2012-03-11 11:11:11.000000000 +2012-03-12 12:12:12.000000000 + +-- !test_timestamp_arithmetic_154 -- +\N +2012-03-01 01:00:02.000000000 +2012-03-02 02:01:03.000000000 +2012-03-03 03:02:04.000000000 +2012-03-04 04:03:05.000000000 +2012-03-05 05:04:06.000000000 +2012-03-06 06:05:07.000000000 +2012-03-07 07:06:08.000000000 +2012-03-08 08:07:09.000000000 +2012-03-09 09:08:10.000000000 +2012-03-10 10:09:11.000000000 +2012-03-11 11:10:12.000000000 +2012-03-12 12:11:13.000000000 + +-- !test_timestamp_arithmetic_155 -- +\N +2012-02-29 01:00:01.000000000 +2012-03-01 02:01:02.000000000 +2012-03-02 03:02:03.000000000 +2012-03-03 04:03:04.000000000 +2012-03-04 05:04:05.000000000 +2012-03-05 06:05:06.000000000 +2012-03-06 07:06:07.000000000 +2012-03-07 08:07:08.000000000 +2012-03-08 09:08:09.000000000 +2012-03-09 10:09:10.000000000 +2012-03-10 11:10:11.000000000 +2012-03-11 12:11:12.000000000 + +-- !test_timestamp_arithmetic_156 -- +\N +2012-03-01 01:00:00.000000000 +2012-03-02 02:01:01.000000000 +2012-03-03 03:02:02.000000000 +2012-03-04 04:03:03.000000000 +2012-03-05 05:04:04.000000000 +2012-03-06 06:05:05.000000000 +2012-03-07 07:06:06.000000000 +2012-03-08 08:07:07.000000000 +2012-03-09 09:08:08.000000000 +2012-03-10 10:09:09.000000000 +2012-03-11 11:10:10.000000000 +2012-03-12 12:11:11.000000000 + +-- !test_timestamp_arithmetic_157 -- +2013-03-01 01:00:01.000000000 +2013-03-02 02:01:02.000000000 +2013-03-03 03:02:03.000000000 +2013-03-04 04:03:04.000000000 +2013-03-05 05:04:05.000000000 +2013-03-06 06:05:06.000000000 +2013-03-07 07:06:07.000000000 +2013-03-08 08:07:08.000000000 +2013-03-09 09:08:09.000000000 +2013-03-10 10:09:10.000000000 +2013-03-11 11:10:11.000000000 +2013-03-12 12:11:12.000000000 + +-- !test_timestamp_arithmetic_158 -- +2012-04-01 01:00:01.000000000 +2012-04-02 02:01:02.000000000 +2012-04-03 03:02:03.000000000 +2012-04-04 04:03:04.000000000 +2012-04-05 05:04:05.000000000 +2012-04-06 06:05:06.000000000 +2012-04-07 07:06:07.000000000 +2012-04-08 08:07:08.000000000 +2012-04-09 09:08:09.000000000 +2012-04-10 10:09:10.000000000 +2012-04-11 11:10:11.000000000 +2012-04-12 12:11:12.000000000 + +-- !test_timestamp_arithmetic_159 -- +2012-03-08 01:00:01.000000000 +2012-03-09 02:01:02.000000000 +2012-03-10 03:02:03.000000000 +2012-03-11 04:03:04.000000000 +2012-03-12 05:04:05.000000000 +2012-03-13 06:05:06.000000000 +2012-03-14 07:06:07.000000000 +2012-03-15 08:07:08.000000000 +2012-03-16 09:08:09.000000000 +2012-03-17 10:09:10.000000000 +2012-03-18 11:10:11.000000000 +2012-03-19 12:11:12.000000000 + +-- !test_timestamp_arithmetic_160 -- +2012-03-02 01:00:01.000000000 +2012-03-03 02:01:02.000000000 +2012-03-04 03:02:03.000000000 +2012-03-05 04:03:04.000000000 +2012-03-06 05:04:05.000000000 +2012-03-07 06:05:06.000000000 +2012-03-08 07:06:07.000000000 +2012-03-09 08:07:08.000000000 +2012-03-10 09:08:09.000000000 +2012-03-11 10:09:10.000000000 +2012-03-12 11:10:11.000000000 +2012-03-13 12:11:12.000000000 + +-- !test_timestamp_arithmetic_161 -- +2012-03-01 02:00:01.000000000 +2012-03-02 03:01:02.000000000 +2012-03-03 04:02:03.000000000 +2012-03-04 05:03:04.000000000 +2012-03-05 06:04:05.000000000 +2012-03-06 07:05:06.000000000 +2012-03-07 08:06:07.000000000 +2012-03-08 09:07:08.000000000 +2012-03-09 10:08:09.000000000 +2012-03-10 11:09:10.000000000 +2012-03-11 12:10:11.000000000 +2012-03-12 13:11:12.000000000 + +-- !test_timestamp_arithmetic_162 -- +2012-03-01 01:01:01.000000000 +2012-03-02 02:02:02.000000000 +2012-03-03 03:03:03.000000000 +2012-03-04 04:04:04.000000000 +2012-03-05 05:05:05.000000000 +2012-03-06 06:06:06.000000000 +2012-03-07 07:07:07.000000000 +2012-03-08 08:08:08.000000000 +2012-03-09 09:09:09.000000000 +2012-03-10 10:10:10.000000000 +2012-03-11 11:11:11.000000000 +2012-03-12 12:12:12.000000000 + +-- !test_timestamp_arithmetic_163 -- +2012-03-01 01:00:02.000000000 +2012-03-02 02:01:03.000000000 +2012-03-03 03:02:04.000000000 +2012-03-04 04:03:05.000000000 +2012-03-05 05:04:06.000000000 +2012-03-06 06:05:07.000000000 +2012-03-07 07:06:08.000000000 +2012-03-08 08:07:09.000000000 +2012-03-09 09:08:10.000000000 +2012-03-10 10:09:11.000000000 +2012-03-11 11:10:12.000000000 +2012-03-12 12:11:13.000000000 + +-- !test_timestamp_arithmetic_164 -- +2013-03-01 01:00:01.000000000 +2013-03-02 02:01:02.000000000 +2013-03-03 03:02:03.000000000 +2013-03-04 04:03:04.000000000 +2013-03-05 05:04:05.000000000 +2013-03-06 06:05:06.000000000 +2013-03-07 07:06:07.000000000 +2013-03-08 08:07:08.000000000 +2013-03-09 09:08:09.000000000 +2013-03-10 10:09:10.000000000 +2013-03-11 11:10:11.000000000 +2013-03-12 12:11:12.000000000 + +-- !test_timestamp_arithmetic_165 -- +2012-04-01 01:00:01.000000000 +2012-04-02 02:01:02.000000000 +2012-04-03 03:02:03.000000000 +2012-04-04 04:03:04.000000000 +2012-04-05 05:04:05.000000000 +2012-04-06 06:05:06.000000000 +2012-04-07 07:06:07.000000000 +2012-04-08 08:07:08.000000000 +2012-04-09 09:08:09.000000000 +2012-04-10 10:09:10.000000000 +2012-04-11 11:10:11.000000000 +2012-04-12 12:11:12.000000000 + +-- !test_timestamp_arithmetic_166 -- +2012-03-08 01:00:01.000000000 +2012-03-09 02:01:02.000000000 +2012-03-10 03:02:03.000000000 +2012-03-11 04:03:04.000000000 +2012-03-12 05:04:05.000000000 +2012-03-13 06:05:06.000000000 +2012-03-14 07:06:07.000000000 +2012-03-15 08:07:08.000000000 +2012-03-16 09:08:09.000000000 +2012-03-17 10:09:10.000000000 +2012-03-18 11:10:11.000000000 +2012-03-19 12:11:12.000000000 + +-- !test_timestamp_arithmetic_167 -- +2012-03-02 01:00:01.000000000 +2012-03-03 02:01:02.000000000 +2012-03-04 03:02:03.000000000 +2012-03-05 04:03:04.000000000 +2012-03-06 05:04:05.000000000 +2012-03-07 06:05:06.000000000 +2012-03-08 07:06:07.000000000 +2012-03-09 08:07:08.000000000 +2012-03-10 09:08:09.000000000 +2012-03-11 10:09:10.000000000 +2012-03-12 11:10:11.000000000 +2012-03-13 12:11:12.000000000 + +-- !test_timestamp_arithmetic_168 -- +2012-03-01 02:00:01.000000000 +2012-03-02 03:01:02.000000000 +2012-03-03 04:02:03.000000000 +2012-03-04 05:03:04.000000000 +2012-03-05 06:04:05.000000000 +2012-03-06 07:05:06.000000000 +2012-03-07 08:06:07.000000000 +2012-03-08 09:07:08.000000000 +2012-03-09 10:08:09.000000000 +2012-03-10 11:09:10.000000000 +2012-03-11 12:10:11.000000000 +2012-03-12 13:11:12.000000000 + +-- !test_timestamp_arithmetic_169 -- +2012-03-01 01:01:01.000000000 +2012-03-02 02:02:02.000000000 +2012-03-03 03:03:03.000000000 +2012-03-04 04:04:04.000000000 +2012-03-05 05:05:05.000000000 +2012-03-06 06:06:06.000000000 +2012-03-07 07:07:07.000000000 +2012-03-08 08:08:08.000000000 +2012-03-09 09:09:09.000000000 +2012-03-10 10:10:10.000000000 +2012-03-11 11:11:11.000000000 +2012-03-12 12:12:12.000000000 + +-- !test_timestamp_arithmetic_170 -- +2012-03-01 01:00:02.000000000 +2012-03-02 02:01:03.000000000 +2012-03-03 03:02:04.000000000 +2012-03-04 04:03:05.000000000 +2012-03-05 05:04:06.000000000 +2012-03-06 06:05:07.000000000 +2012-03-07 07:06:08.000000000 +2012-03-08 08:07:09.000000000 +2012-03-09 09:08:10.000000000 +2012-03-10 10:09:11.000000000 +2012-03-11 11:10:12.000000000 +2012-03-12 12:11:13.000000000 + +-- !test_timestamp_arithmetic_171 -- +2012-02-29 01:00:01.000000000 +2012-03-01 02:01:02.000000000 +2012-03-02 03:02:03.000000000 +2012-03-03 04:03:04.000000000 +2012-03-04 05:04:05.000000000 +2012-03-05 06:05:06.000000000 +2012-03-06 07:06:07.000000000 +2012-03-07 08:07:08.000000000 +2012-03-08 09:08:09.000000000 +2012-03-09 10:09:10.000000000 +2012-03-10 11:10:11.000000000 +2012-03-11 12:11:12.000000000 + +-- !test_timestamp_arithmetic_172 -- +2012-03-01 01:00:00.000000000 +2012-03-02 02:01:01.000000000 +2012-03-03 03:02:02.000000000 +2012-03-04 04:03:03.000000000 +2012-03-05 05:04:04.000000000 +2012-03-06 06:05:05.000000000 +2012-03-07 07:06:06.000000000 +2012-03-08 08:07:07.000000000 +2012-03-09 09:08:08.000000000 +2012-03-10 10:09:09.000000000 +2012-03-11 11:10:10.000000000 +2012-03-12 12:11:11.000000000 + diff --git a/regression-test/data/query_p0/show/test_show_data_types.out b/regression-test/data/query_p0/show/test_show_data_types.out index de1d757cbf80cd..209356913a856c 100644 --- a/regression-test/data/query_p0/show/test_show_data_types.out +++ b/regression-test/data/query_p0/show/test_show_data_types.out @@ -26,6 +26,7 @@ MAP 24 QUANTILE_STATE 16 SMALLINT 2 STRING 16 +TIMESTAMP_NS 8 TINYINT 1 VARCHAR 16 diff --git a/regression-test/data/types/test_show_data_types.out b/regression-test/data/types/test_show_data_types.out index e6f69c6718123e..096b266a37e618 100644 --- a/regression-test/data/types/test_show_data_types.out +++ b/regression-test/data/types/test_show_data_types.out @@ -26,6 +26,7 @@ MAP 24 QUANTILE_STATE 16 SMALLINT 2 STRING 16 +TIMESTAMP_NS 8 TINYINT 1 VARCHAR 16 diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_agg_state.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_agg_state.groovy new file mode 100644 index 00000000000000..dd5ac1a92ebccf --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_agg_state.groovy @@ -0,0 +1,42 @@ +// 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. + +suite("test_timestamp_ns_agg_state") { + sql "set enable_agg_state = true" + sql "drop table if exists timestamp_ns_agg_state" + sql """ + create table timestamp_ns_agg_state ( + id int, + dt_state agg_state generic + ) + aggregate key(id) + distributed by hash(id) buckets 1 + properties("replication_num" = "1") + """ + sql """ + insert into timestamp_ns_agg_state values + (1, max_state(cast('1677-09-21 00:12:43.145224192' as timestamp_ns))), + (1, max_state(cast('1970-01-01 00:00:00.000000000' as timestamp_ns))), + (1, max_state(cast('2262-04-11 23:47:16.854775807' as timestamp_ns))) + """ + order_qt_aggregate_state """ + select id, max_merge(dt_state) + from timestamp_ns_agg_state + group by id + order by id + """ +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_binary_output.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_binary_output.groovy new file mode 100644 index 00000000000000..3d0a0fda568585 --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_binary_output.groovy @@ -0,0 +1,63 @@ +// 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. + +import com.mysql.cj.jdbc.ServerPreparedStatement + +import java.sql.PreparedStatement +import java.sql.Types + +suite("test_timestamp_ns_binary_output") { + def user = context.config.jdbcUser + def password = context.config.jdbcPassword + + sql "drop table if exists test_timestamp_ns_binary_output" + sql """ + create table test_timestamp_ns_binary_output ( + id int, + dt timestamp_ns + ) + duplicate key(id) + distributed by hash(id) buckets 1 + properties("replication_num" = "1") + """ + sql """ + insert into test_timestamp_ns_binary_output values + (1, '1677-09-21 00:12:43.145224192'), + (2, '1969-12-31 23:59:59.999999999'), + (3, '1970-01-01 00:00:00.000000000'), + (4, '1970-01-01 00:00:00.000000001'), + (5, '2262-04-11 23:47:16.854775807'), + (6, null) + """ + + order_qt_text_protocol """ + select id, dt from test_timestamp_ns_binary_output order by id + """ + + String url = getServerPrepareJdbcUrl( + context.config.jdbcUrl, context.dbName) + connect(user, password, url) { + PreparedStatement stmt = prepareStatement(""" + select id, dt from test_timestamp_ns_binary_output where id >= ? order by id + """) + assertEquals(ServerPreparedStatement, stmt.class) + assertEquals(Types.CHAR, stmt.metaData.getColumnType(2)) + stmt.setInt(1, 1) + qe_binary_protocol stmt + stmt.close() + } +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_cast.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_cast.groovy new file mode 100644 index 00000000000000..03b2dd8746a78c --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_cast.groovy @@ -0,0 +1,395 @@ +// 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. + +suite("test_timestamp_ns_cast") { + sql "set time_zone = '+08:00'" + sql "set enable_strict_cast = false" + setFeConfigTemporary([ + enable_variant_v2: true, + disable_datev1: false, + disable_decimalv2: false + ]) { + + sql "drop table if exists timestamp_ns_cast_string" + sql """ + create table timestamp_ns_cast_string ( + id int, + value string + ) + duplicate key(id) + distributed by hash(id) buckets 1 + properties("replication_num" = "1") + """ + sql """ + insert into timestamp_ns_cast_string values + (1, '1677-09-21 00:12:43.1452241914'), + (2, '1677-09-21 00:12:43.1452241915'), + (3, '1969-12-31 23:59:59.999999999'), + (4, '1970-01-01 00:00:00.000000000'), + (5, '2024-02-29 12:34:56.1234567894'), + (6, '2024-02-29 12:34:56.1234567895'), + (7, '2024-02-29 12:34:56.9999999995'), + (8, '2262-04-11 23:47:16.8547758074'), + (9, '2262-04-11 23:47:16.8547758075'), + (10, '2024-02-29 12:34:56.123456789+08:00'), + (11, '2024-02-29T04:34:56.123456789Z'), + (12, '2024-02-30 12:34:56.123456789'), + (13, '2024-01-01 00:00:00.123.456'), + (14, null) + """ + order_qt_string_to_timestamp_ns """ + select id, cast(value as timestamp_ns) + from timestamp_ns_cast_string + order by id + """ + + sql "set debug_skip_fold_constant = false" + qt_string_literal_fold """ + select + cast('1677-09-21 00:12:43.1452241915' as timestamp_ns), + cast('1970-01-01 00:00:00.000000000' as timestamp_ns), + cast('2024-02-29 12:34:56.9999999995' as timestamp_ns), + cast('2262-04-11 23:47:16.8547758074' as timestamp_ns) + """ + sql "set debug_skip_fold_constant = true" + qt_string_literal_runtime """ + select + cast('1677-09-21 00:12:43.1452241915' as timestamp_ns), + cast('1970-01-01 00:00:00.000000000' as timestamp_ns), + cast('2024-02-29 12:34:56.9999999995' as timestamp_ns), + cast('2262-04-11 23:47:16.8547758074' as timestamp_ns) + """ + sql "set debug_skip_fold_constant = false" + + qt_numeric_to_timestamp_ns """ + select + cast(cast(123 as tinyint) as timestamp_ns), + cast(cast(1231 as smallint) as timestamp_ns), + cast(cast(20240229 as int) as timestamp_ns), + cast(cast(20240229123456 as bigint) as timestamp_ns), + cast(cast(20240229123456 as largeint) as timestamp_ns), + cast(cast(20240229123456.125 as float) as timestamp_ns), + cast(cast(20240229123456.125 as double) as timestamp_ns), + cast(cast(20240229123456.1234567895 as decimal(24, 10)) as timestamp_ns), + cast(cast(20240229123456.123456789 as decimalv2(27, 9)) as timestamp_ns) + """ + + qt_datelike_to_timestamp_ns """ + select + cast(cast('1970-01-01' as date) as timestamp_ns), + cast(cast('1970-01-01' as datev2) as timestamp_ns), + cast(cast('2024-02-29 12:34:56' as datetime) as timestamp_ns), + cast(cast('2024-02-29 12:34:56.123456' as datetimev2(6)) as timestamp_ns), + cast(cast(cast('12:34:56.123456' as time(6)) as timestamp_ns) as time(6)), + cast(cast('2024-02-29 04:34:56.123456+00:00' as timestamptz(6)) as timestamp_ns) + """ + + def allSupportedSourcesSql = """ + select + cast(cast(123 as tinyint) as timestamp_ns), + cast(cast(1231 as smallint) as timestamp_ns), + cast(cast(20240229 as int) as timestamp_ns), + cast(cast(20240229123456 as bigint) as timestamp_ns), + cast(cast(20240229123456 as largeint) as timestamp_ns), + cast(cast(123 as float) as timestamp_ns), + cast(cast(20240229123456.125 as double) as timestamp_ns), + cast(cast(20240229123456.1234567895 as decimal(24, 10)) as timestamp_ns), + cast(cast('20240229123456.123456789' as decimalv2(27, 9)) as timestamp_ns), + cast(cast('1970-01-01' as date) as timestamp_ns), + cast(cast('1970-01-01' as datev2) as timestamp_ns), + cast(cast('2024-02-29 12:34:56' as datetime) as timestamp_ns), + cast(cast('2024-02-29 12:34:56.123456' as datetimev2(6)) as timestamp_ns), + cast(cast(cast('12:34:56.123456' as time(6)) as timestamp_ns) as time(6)), + cast(cast('2024-02-29 12:34:56.123456789' as char(40)) as timestamp_ns), + cast(cast('2024-02-29 12:34:56.123456789+08:00' as varchar(40)) as timestamp_ns), + cast(cast('2024-02-29T04:34:56.123456789Z' as string) as timestamp_ns), + cast(cast('2024-02-29 04:34:56.123456+00:00' as timestamptz(6)) as timestamp_ns), + cast(parse_to_variant('\"2024-02-29 12:34:56.123456789\"') as timestamp_ns), + cast(cast('2024-02-29 12:34:56.123456789' as timestamp_ns) as timestamp_ns), + cast(null as timestamp_ns) + """ + def allSupportedTargetsSql = """ + select + cast(cast('2024-02-29 12:34:56.123456789' as timestamp_ns) as bigint), + cast(cast('2024-02-29 12:34:56.123456789' as timestamp_ns) as largeint), + cast(cast('2024-02-29 12:34:56.123456789' as timestamp_ns) as date), + cast(cast('2024-02-29 12:34:56.123456789' as timestamp_ns) as datev2), + cast(cast('2024-02-29 12:34:56.123456789' as timestamp_ns) as datetime), + cast(cast('2024-02-29 12:34:56.123456789' as timestamp_ns) as datetimev2(6)), + cast(cast('2024-02-29 12:34:56.123456789' as timestamp_ns) as time(6)), + cast(cast('2024-02-29 12:34:56.123456789' as timestamp_ns) as char(40)), + cast(cast('2024-02-29 12:34:56.123456789' as timestamp_ns) as varchar(40)), + cast(cast('2024-02-29 12:34:56.123456789' as timestamp_ns) as string), + cast(cast('2024-02-29 12:34:56.123456789' as timestamp_ns) as variant), + cast(cast('2024-02-29 12:34:56.123456789' as timestamp_ns) as timestamptz(6)), + cast(cast('2024-02-29 12:34:56.123456789' as timestamp_ns) as float), + cast(cast('2024-02-29 12:34:56.123456789' as timestamp_ns) as double), + cast(cast('2024-02-29 12:34:56.123456789' as timestamp_ns) as timestamp_ns) + """ + sql "set debug_skip_fold_constant = false" + qt_all_supported_sources_fold allSupportedSourcesSql + qt_all_supported_targets_fold allSupportedTargetsSql + sql "set debug_skip_fold_constant = true" + qt_all_supported_sources_runtime allSupportedSourcesSql + qt_all_supported_targets_runtime allSupportedTargetsSql + sql "set debug_skip_fold_constant = false" + testFoldConst(allSupportedSourcesSql) + testFoldConst(allSupportedTargetsSql) + + sql "drop table if exists timestamp_ns_cast_typed_source" + sql """ + create table timestamp_ns_cast_typed_source ( + id int, + tiny_value tinyint, + small_value smallint, + int_value int, + bigint_value bigint, + largeint_value largeint, + float_value float, + double_value double, + decimalv3_value decimal(24, 10), + decimalv2_value decimalv2(27, 9), + date_value date, + datev2_value datev2, + datetime_value datetime, + datetimev2_value datetimev2(6), + time_text varchar(32), + char_value char(40), + varchar_value varchar(40), + string_value string, + timestamptz_value timestamptz(6), + variant_value variant + ) + duplicate key(id) + distributed by hash(id) buckets 1 + properties("replication_num" = "1") + """ + sql """ + insert into timestamp_ns_cast_typed_source values + (1, 123, 1231, 20240229, 20240229123456, 20240229123456, 123, + 20240229123456.125, 20240229123456.1234567895, + cast('20240229123456.123456789' as decimalv2(27, 9)), + '1970-01-01', '1970-01-01', '2024-02-29 12:34:56', + '2024-02-29 12:34:56.123456', '12:34:56.123456', + '2024-02-29 12:34:56.123456789', '2024-02-29 12:34:56.123456789+08:00', + '2024-02-29T04:34:56.123456789Z', + cast('2024-02-29 04:34:56.123456+00:00' as timestamptz(6)), + parse_to_variant('\"2024-02-29 12:34:56.123456789\"')), + (2, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null) + """ + order_qt_typed_columns_to_timestamp_ns """ + select id, + cast(tiny_value as timestamp_ns), + cast(small_value as timestamp_ns), + cast(int_value as timestamp_ns), + cast(bigint_value as timestamp_ns), + cast(largeint_value as timestamp_ns), + cast(float_value as timestamp_ns), + cast(double_value as timestamp_ns), + cast(decimalv3_value as timestamp_ns), + cast(decimalv2_value as timestamp_ns), + cast(date_value as timestamp_ns), + cast(datev2_value as timestamp_ns), + cast(datetime_value as timestamp_ns), + cast(datetimev2_value as timestamp_ns), + cast(cast(cast(time_text as time(6)) as timestamp_ns) as time(6)), + cast(char_value as timestamp_ns), + cast(varchar_value as timestamp_ns), + cast(string_value as timestamp_ns), + cast(timestamptz_value as timestamp_ns), + cast(variant_value as timestamp_ns) + from timestamp_ns_cast_typed_source + order by id + """ + + sql "drop table if exists timestamp_ns_cast_source" + sql """ + create table timestamp_ns_cast_source ( + id int, + value timestamp_ns + ) + duplicate key(id) + distributed by hash(id) buckets 1 + properties("replication_num" = "1") + """ + sql """ + insert into timestamp_ns_cast_source values + (1, '1677-09-21 00:12:43.145224192'), + (2, '1969-12-31 23:59:59.999999999'), + (3, '1970-01-01 00:00:00.000000000'), + (4, '2024-02-29 12:34:56.123456789'), + (5, '2262-04-11 23:47:16.854775807'), + (6, null) + """ + order_qt_timestamp_ns_to_supported_types """ + select id, + cast(value as date), + cast(value as datev2), + cast(value as datetime), + cast(value as datetimev2(0)), + cast(value as datetimev2(3)), + cast(value as datetimev2(6)), + cast(value as time(0)), + cast(value as time(3)), + cast(value as time(6)), + cast(value as bigint), + cast(value as largeint), + cast(value as timestamp_ns), + cast(value as char(40)), + cast(value as varchar(40)), + cast(value as string), + cast(value as variant), + cast(value as timestamptz(6)), + cast(value as float), + cast(value as double) + from timestamp_ns_cast_source + order by id + """ + + order_qt_variant_round_trip """ + select id, cast(cast(value as variant) as timestamp_ns) + from timestamp_ns_cast_source + order by id + """ + + sql "drop table if exists timestamp_ns_cast_datelike_boundary" + sql """ + create table timestamp_ns_cast_datelike_boundary ( + id int, + datetimev2_value datetimev2(6), + timestamptz_value timestamptz(6) + ) + duplicate key(id) + distributed by hash(id) buckets 1 + properties("replication_num" = "1") + """ + sql """ + insert into timestamp_ns_cast_datelike_boundary values + (1, '1677-09-21 00:12:43.145224', + cast('1677-09-21 00:12:43.145224+08:00' as timestamptz(6))), + (2, '1677-09-21 00:12:43.145225', + cast('1677-09-21 00:12:43.145225+08:00' as timestamptz(6))), + (3, '2262-04-11 23:47:16.854775', + cast('2262-04-11 23:47:16.854775+08:00' as timestamptz(6))), + (4, '2262-04-11 23:47:16.854776', + cast('2262-04-11 23:47:16.854776+08:00' as timestamptz(6))) + """ + + order_qt_datelike_boundary_non_strict """ + select id, + cast(datetimev2_value as timestamp_ns), + cast(timestamptz_value as timestamp_ns) + from timestamp_ns_cast_datelike_boundary + order by id + """ + + def datelikeBoundaryConstantSql = """ + select + cast(cast('1677-09-21 00:12:43.145224' as datetimev2(6)) as timestamp_ns), + cast(cast('1677-09-21 00:12:43.145225' as datetimev2(6)) as timestamp_ns), + cast(cast('2262-04-11 23:47:16.854775' as datetimev2(6)) as timestamp_ns), + cast(cast('2262-04-11 23:47:16.854776' as datetimev2(6)) as timestamp_ns), + cast(cast('1677-09-21 00:12:43.145224+08:00' as timestamptz(6)) as timestamp_ns), + cast(cast('1677-09-21 00:12:43.145225+08:00' as timestamptz(6)) as timestamp_ns), + cast(cast('2262-04-11 23:47:16.854775+08:00' as timestamptz(6)) as timestamp_ns), + cast(cast('2262-04-11 23:47:16.854776+08:00' as timestamptz(6)) as timestamp_ns) + """ + qt_datelike_boundary_constants_non_strict datelikeBoundaryConstantSql + testFoldConst(datelikeBoundaryConstantSql) + + // Rounding to a microsecond destination can carry to the next second. At the lower + // TIMESTAMP_NS boundary it may also produce a valid DATETIMEV2 value below that boundary. + qt_fraction_discard_and_carry """ + select + cast(cast('1677-09-21 00:12:43.145224192' as timestamp_ns) as datetimev2(6)), + cast(cast('1969-12-31 23:59:59.999999499' as timestamp_ns) as datetimev2(6)), + cast(cast('1969-12-31 23:59:59.999999500' as timestamp_ns) as datetimev2(6)), + cast(cast('2262-04-11 23:47:16.854775807' as timestamp_ns) as datetimev2(6)) + """ + + qt_fraction_discard_and_carry_timestamptz """ + select + cast(cast('1677-09-21 00:12:43.145224192' as timestamp_ns) as timestamptz(6)), + cast(cast('1969-12-31 23:59:59.999999499' as timestamp_ns) as timestamptz(6)), + cast(cast('1969-12-31 23:59:59.999999500' as timestamp_ns) as timestamptz(6)), + cast(cast('2262-04-11 23:47:16.854775807' as timestamp_ns) as timestamptz(6)) + """ + + sql "set enable_strict_cast = true" + test { + sql """ + select cast(datetimev2_value as timestamp_ns) + from timestamp_ns_cast_datelike_boundary + where id = 1 + """ + exception "TIMESTAMP_NS overflow" + } + test { + sql """ + select cast(timestamptz_value as timestamp_ns) + from timestamp_ns_cast_datelike_boundary + where id = 1 + """ + exception "can not cast timestamptz" + } + test { + sql "select cast(cast('2262-04-11 23:47:16.854776' as datetimev2(6)) as timestamp_ns)" + exception "outside Int64 epoch nanosecond range" + } + test { + sql """ + select cast(cast('2262-04-11 23:47:16.854776+08:00' as timestamptz(6)) + as timestamp_ns) + """ + exception "can not cast timestamptz" + } + for (def badValue : [ + ["1677-09-21 00:12:43.1452241914", "outside Int64 epoch nanosecond range"], + ["2262-04-11 23:47:16.8547758075", "outside Int64 epoch nanosecond range"], + ["2024-02-30 12:34:56.123456789", "is invalid"], + ["2024-01-01 00:00:00.123.456", "can't cast to timestamp_ns"]]) { + test { + sql "select cast('${badValue[0]}' as timestamp_ns)" + exception badValue[1] + } + } + sql "set enable_strict_cast = false" + + for (def targetType : [ + "boolean", "tinyint", "smallint", "int", "decimalv2(27, 9)", "decimal(38, 9)", + "json", "ipv4", "ipv6", "varbinary", "hll", "bitmap", "quantile_state", + "array", "map", "struct"]) { + test { + sql "select cast(value as ${targetType}) from timestamp_ns_cast_source" + exception "cast" + } + } + for (def sourceExpr : [ + "true", "cast('2024-01-01' as json)", "cast('127.0.0.1' as ipv4)", + "cast('2001:db8::1' as ipv6)", "cast('timestamp_ns' as varbinary)", + "hll_hash('timestamp_ns')", "bitmap_from_string('1,2')", + "to_quantile_state(1, 2048)", "array(20240229)", "map(1, 20240229)", + "named_struct('a', 20240229)", + "max_state(cast('2024-01-01 00:00:00' as timestamp_ns))"]) { + test { + sql "select cast(${sourceExpr} as timestamp_ns)" + exception "cast" + } + } + } +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_complex_type.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_complex_type.groovy new file mode 100644 index 00000000000000..a7a5acac50cd7b --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_complex_type.groovy @@ -0,0 +1,60 @@ +// 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. + +suite("test_timestamp_ns_complex_type") { + sql "drop table if exists timestamp_ns_complex_type" + sql """ + create table timestamp_ns_complex_type ( + id int, + dt_array array, + dt_map map, + dt_struct struct, + dt_json json + ) + duplicate key(id) + distributed by hash(id) buckets 1 + properties("replication_num" = "1") + """ + sql """ + insert into timestamp_ns_complex_type values + (1, + array( + cast('1677-09-21 00:12:43.145224192' as timestamp_ns), + cast('1970-01-01 00:00:00.123456789' as timestamp_ns), + cast('2262-04-11 23:47:16.854775807' as timestamp_ns)), + map( + 'before', cast('1969-12-31 23:59:59.999999999' as timestamp_ns), + 'after', cast('1970-01-01 00:00:00.000000001' as timestamp_ns)), + named_struct( + 'minimum', cast('1677-09-21 00:12:43.145224192' as timestamp_ns), + 'maximum', cast('2262-04-11 23:47:16.854775807' as timestamp_ns)), + json_object('dt', '1970-01-01 00:00:00.123456789')), + (2, null, null, null, null) + """ + + order_qt_complex_storage """ + select id, dt_array, dt_map, dt_struct, dt_json + from timestamp_ns_complex_type + order by id + """ + order_qt_json_round_trip """ + select cast(json_extract_string(dt_json, '\$.dt') as timestamp_ns) + from timestamp_ns_complex_type + where dt_json is not null + order by id + """ +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_count_distinct.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_count_distinct.groovy new file mode 100644 index 00000000000000..38d3415e14fb2e --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_count_distinct.groovy @@ -0,0 +1,44 @@ +// 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. + +suite("test_timestamp_ns_count_distinct") { + sql "drop table if exists timestamp_ns_count_distinct" + sql """ + create table timestamp_ns_count_distinct ( + id int, + dt timestamp_ns + ) + duplicate key(id) + distributed by hash(id) buckets 2 + properties("replication_num" = "1") + """ + sql """ + insert into timestamp_ns_count_distinct values + (1, '1677-09-21 00:12:43.145224192'), + (2, '1970-01-01 00:00:00.000000000'), + (3, '1970-01-01 00:00:00.000000000'), + (4, '1970-01-01 00:00:00.000000001'), + (5, '2262-04-11 23:47:16.854775807'), + (6, null) + """ + + qt_count "select count(*), count(dt) from timestamp_ns_count_distinct" + qt_count_distinct """ + select count(distinct dt), multi_distinct_count(dt), approx_count_distinct(dt) + from timestamp_ns_count_distinct + """ +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_delete.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_delete.groovy new file mode 100644 index 00000000000000..f6d333484805b9 --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_delete.groovy @@ -0,0 +1,54 @@ +// 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. + +suite("test_timestamp_ns_delete") { + sql "drop table if exists timestamp_ns_delete" + sql """ + create table timestamp_ns_delete ( + dt timestamp_ns, + id int, + value varchar(16) + ) + unique key(dt, id) + distributed by hash(dt) buckets 2 + properties( + "replication_num" = "1", + "enable_unique_key_merge_on_write" = "true" + ) + """ + sql """ + insert into timestamp_ns_delete values + ('1677-09-21 00:12:43.145224192', 1, 'minimum'), + ('1969-12-31 23:59:59.999999999', 2, 'before'), + ('1970-01-01 00:00:00.000000000', 3, 'epoch'), + ('1970-01-01 00:00:00.000000001', 4, 'after'), + ('2262-04-11 23:47:16.854775807', 5, 'maximum') + """ + order_qt_before "select dt, id, value from timestamp_ns_delete order by dt, id" + + sql "delete from timestamp_ns_delete where dt = '1969-12-31 23:59:59.999999999'" + order_qt_after_eq "select dt, id, value from timestamp_ns_delete order by dt, id" + + sql """ + delete from timestamp_ns_delete + where dt in ('1677-09-21 00:12:43.145224192', '2262-04-11 23:47:16.854775807') + """ + order_qt_after_in "select dt, id, value from timestamp_ns_delete order by dt, id" + + sql "delete from timestamp_ns_delete where dt >= '1970-01-01 00:00:00.000000001'" + order_qt_after_range "select dt, id, value from timestamp_ns_delete order by dt, id" +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_expressions.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_expressions.groovy new file mode 100644 index 00000000000000..95fec18441ce83 --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_expressions.groovy @@ -0,0 +1,253 @@ +// 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. + +suite("test_timestamp_ns_expressions") { + sql "set time_zone = '+08:00'" + sql "drop table if exists timestamp_ns_expressions" + sql """ + create table timestamp_ns_expressions ( + id int, + value timestamp_ns, + fallback timestamp_ns + ) + duplicate key(id) + distributed by hash(id) buckets 1 + properties("replication_num" = "1") + """ + sql """ + insert into timestamp_ns_expressions values + (1, '1677-09-21 00:12:43.145224192', '1970-01-01 00:00:00.000000000'), + (2, '1969-12-31 23:59:59.999999999', '1970-01-01 00:00:00.000000001'), + (3, '1970-01-01 00:00:00.000000000', '2024-02-29 12:34:56.123456789'), + (4, '1970-01-01 00:00:00.000000001', null), + (5, '2262-04-11 23:47:16.854775807', '2262-04-11 23:47:16.854775807'), + (6, null, '1970-01-01 00:00:00.000000000'), + (7, null, null) + """ + + order_qt_comparisons """ + select id, + value = fallback, + value != fallback, + value > fallback, + value >= fallback, + value < fallback, + value <= fallback, + value <=> fallback + from timestamp_ns_expressions + order by id + """ + order_qt_null_predicates """ + select id, value is null, value is not null + from timestamp_ns_expressions + order by id + """ + order_qt_in_not_in """ + select id, + value in ( + cast('1677-09-21 00:12:43.145224192' as timestamp_ns), + cast('1970-01-01 00:00:00.000000000' as timestamp_ns)), + value not in ( + cast('1677-09-21 00:12:43.145224192' as timestamp_ns), + cast('1970-01-01 00:00:00.000000000' as timestamp_ns)), + value in ( + cast('1970-01-01 00:00:00.000000000' as timestamp_ns), null), + value not in ( + cast('1970-01-01 00:00:00.000000000' as timestamp_ns), null) + from timestamp_ns_expressions + order by id + """ + order_qt_between """ + select id, + value between cast('1969-12-31 23:59:59.999999999' as timestamp_ns) + and cast('1970-01-01 00:00:00.000000001' as timestamp_ns), + value not between cast('1969-12-31 23:59:59.999999999' as timestamp_ns) + and cast('1970-01-01 00:00:00.000000001' as timestamp_ns) + from timestamp_ns_expressions + order by id + """ + order_qt_boolean_composition """ + select id, + (value is null or value >= cast('1970-01-01 00:00:00.000000000' as timestamp_ns)), + not (value <=> fallback), + (value is not null and fallback is not null) + from timestamp_ns_expressions + order by id + """ + + order_qt_condition_result """ + select id, + if(id % 2 = 0, value, fallback), + ifnull(value, fallback), + coalesce(value, fallback, + cast('1970-01-01 00:00:00.000000000' as timestamp_ns)), + nullif(value, fallback), + case + when id = 1 then value + when id = 2 then fallback + when id = 3 then cast('1970-01-01 00:00:00.000000001' as timestamp_ns) + else null + end + from timestamp_ns_expressions + order by id + """ + + // DATETIMEV2 has only microsecond precision, so a mixed conditional expression must widen + // it to TIMESTAMP_NS without truncating the nanosecond branch. + order_qt_mixed_condition_result """ + select id, + if(id % 2 = 0, value, + cast('2024-02-29 12:34:56.123456' as datetimev2(6))), + case when id % 2 = 0 then value + else cast('2024-02-29 12:34:56.123456' as datetimev2(6)) end + from timestamp_ns_expressions + order by id + """ + + sql "drop table if exists timestamp_ns_mixed_temporal" + sql """ + create table timestamp_ns_mixed_temporal ( + id int, + ts timestamp_ns, + dt datetimev2(6), + tz timestamptz(6), + time_text varchar(32) + ) + duplicate key(id) + distributed by hash(id) buckets 1 + properties("replication_num" = "1") + """ + sql """ + insert into timestamp_ns_mixed_temporal values + (1, '2024-02-29 12:34:56.123456789', '2024-02-29 12:34:56.123456', + cast('2024-02-29 04:34:56.123456+00:00' as timestamptz(6)), '12:34:56.123456'), + (2, '2024-02-29 12:34:56.123456000', '2024-02-29 12:34:56.123456', + cast('2024-02-29 04:34:56.123456+00:00' as timestamptz(6)), '12:34:56.123456'), + (3, null, '2024-02-29 12:34:56.123456', + cast('2024-02-29 04:34:56.123456+00:00' as timestamptz(6)), '12:34:56.123456') + """ + + // Mixed comparisons must promote DATETIMEV2 and TIMESTAMPTZ to TIMESTAMP_NS. Row 1 + // deliberately differs only below microsecond precision, while row 2 is exactly equal. + order_qt_mixed_temporal_comparisons """ + select id, + ts = dt, ts != dt, ts > dt, ts >= dt, ts < dt, ts <= dt, ts <=> dt, + ts = tz, ts != tz, ts > tz, ts >= tz, ts < tz, ts <= tz, ts <=> tz + from timestamp_ns_mixed_temporal + order by id + """ + order_qt_mixed_temporal_in """ + select id, + ts in (dt, tz, cast(time_text as time(6))), + ts not in (dt, tz, cast(time_text as time(6))) + from timestamp_ns_mixed_temporal + order by id + """ + qt_mixed_time_comparisons """ + select + cast('1677-09-21 00:12:43.145224192' as timestamp_ns) + < cast('12:34:56.123456' as time(6)), + cast('2262-04-11 23:47:16.854775807' as timestamp_ns) + > cast('12:34:56.123456' as time(6)) + """ + + order_qt_mixed_temporal_conditions """ + select id, + if(id = 1, ts, dt), + if(id = 1, ts, tz), + cast(if(id = 1, ts, cast(time_text as time(6))) as time(6)), + ifnull(ts, dt), + ifnull(ts, tz), + cast(ifnull(ts, cast(time_text as time(6))) as time(6)), + coalesce(ts, dt, tz), + nullif(ts, dt), + nullif(ts, tz), + case when id = 1 then ts + when id = 2 then dt + else tz end, + cast(case when id = 1 then ts + when id = 2 then dt + when id = 3 then tz + else cast(time_text as time(6)) end as time(6)) + from timestamp_ns_mixed_temporal + order by id + """ + + order_qt_mixed_temporal_functions """ + select id, + datediff(ts, dt), timediff(ts, dt), seconds_diff(ts, dt), + datediff(ts, tz), timediff(ts, tz), seconds_diff(ts, tz), + field(ts, + cast('2024-02-29 12:34:56.123456' as datetimev2(6)), + cast('2024-02-29 04:34:56.123456+00:00' as timestamptz(6)), + cast('12:34:56.123456' as time(6))) + from timestamp_ns_mixed_temporal + order by id + """ + + def mixedTemporalConstantsSql = """ + select + cast('2024-02-29 12:34:56.123456789' as timestamp_ns) + > cast('2024-02-29 12:34:56.123456' as datetimev2(6)), + cast('2024-02-29 12:34:56.123456789' as timestamp_ns) + > cast('2024-02-29 04:34:56.123456+00:00' as timestamptz(6)), + cast('1677-09-21 00:12:43.145224192' as timestamp_ns) + < cast('12:34:56.123456' as time(6)), + if(true, cast('2024-02-29 12:34:56.123456789' as timestamp_ns), + cast('2024-02-29 12:34:56.123456' as datetimev2(6))), + if(true, cast('2024-02-29 12:34:56.123456789' as timestamp_ns), + cast('2024-02-29 04:34:56.123456+00:00' as timestamptz(6))), + cast(if(false, cast('2024-02-29 12:34:56.123456789' as timestamp_ns), + cast('12:34:56.123456' as time(6))) as time(6)), + ifnull(cast(null as timestamp_ns), + cast('2024-02-29 12:34:56.123456' as datetimev2(6))), + coalesce(cast(null as timestamp_ns), + cast('2024-02-29 04:34:56.123456+00:00' as timestamptz(6))), + nullif(cast('2024-02-29 12:34:56.123456789' as timestamp_ns), + cast('2024-02-29 12:34:56.123456' as datetimev2(6))), + datediff(cast('2024-02-29 12:34:56.123456789' as timestamp_ns), + cast('2024-02-29 04:34:56.123456+00:00' as timestamptz(6))), + timediff(cast('2024-02-29 12:34:56.123456789' as timestamp_ns), + cast('2024-02-29 04:34:56.123456+00:00' as timestamptz(6))), + seconds_diff(cast('2024-02-29 12:34:56.123456789' as timestamp_ns), + cast('2024-02-29 04:34:56.123456+00:00' as timestamptz(6))) + """ + qt_mixed_temporal_constants mixedTemporalConstantsSql + testFoldConst(mixedTemporalConstantsSql) + + sql "set debug_skip_fold_constant = false" + qt_folded_conditions """ + select + if(true, + cast('1970-01-01 00:00:00.000000001' as timestamp_ns), + cast('1970-01-01 00:00:00.000000002' as timestamp_ns)), + coalesce(null, cast('1970-01-01 00:00:00.000000001' as timestamp_ns)), + cast('1970-01-01 00:00:00.000000001' as timestamp_ns) + in (cast('1970-01-01 00:00:00.000000001' as timestamp_ns)) + """ + sql "set debug_skip_fold_constant = true" + qt_runtime_conditions """ + select + if(true, + cast('1970-01-01 00:00:00.000000001' as timestamp_ns), + cast('1970-01-01 00:00:00.000000002' as timestamp_ns)), + coalesce(null, cast('1970-01-01 00:00:00.000000001' as timestamp_ns)), + cast('1970-01-01 00:00:00.000000001' as timestamp_ns) + in (cast('1970-01-01 00:00:00.000000001' as timestamp_ns)) + """ + sql "set debug_skip_fold_constant = false" +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_functions.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_functions.groovy new file mode 100644 index 00000000000000..be1b1b9fb3d456 --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_functions.groovy @@ -0,0 +1,407 @@ +// 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. + +suite("test_timestamp_ns_functions") { + sql "set time_zone = '+08:00'" + sql "drop table if exists timestamp_ns_functions" + sql """ + create table timestamp_ns_functions ( + id int, + value timestamp_ns + ) + duplicate key(id) + distributed by hash(id) buckets 1 + properties("replication_num" = "1") + """ + sql """ + insert into timestamp_ns_functions values + (1, '1677-09-21 00:12:43.145224192'), + (2, '1969-12-31 23:59:59.999999999'), + (3, '1970-01-01 00:00:00.000000000'), + (4, '1970-01-01 00:00:00.000000001'), + (5, '2024-02-29 12:34:56.123456789'), + (6, '2262-04-11 23:47:16.854775807'), + (7, null) + """ + + def scalarFunctionConstantsSql = """ + select + year(cast('2024-02-29 12:34:56.123456789' as timestamp_ns)), + date_format(cast('2024-02-29 12:34:56.123456789' as timestamp_ns), + '%Y-%m-%d %H:%i:%s.%f'), + time(cast('2024-02-29 12:34:56.123456789' as timestamp_ns)), + seconds_add(cast('1969-12-31 23:59:59.999999999' as timestamp_ns), 1), + timediff(cast('1970-01-01 00:00:01.123456789' as timestamp_ns), + cast('1969-12-31 23:59:59.999999999' as timestamp_ns)), + date_trunc(cast('2024-02-29 12:34:56.123456789' as timestamp_ns), 'second'), + second_floor(cast('2024-02-29 12:34:56.123456789' as timestamp_ns)), + second_ceil(cast('2024-02-29 12:34:56.123456789' as timestamp_ns)), + convert_tz(cast('2024-02-29 12:34:56.123456789' as timestamp_ns), + '+08:00', '+00:00'), + sequence(cast('1969-12-31 23:59:59.000000001' as timestamp_ns), + cast('1970-01-01 00:00:02.000000001' as timestamp_ns), interval 1 second) + """ + sql "set debug_skip_fold_constant = false" + qt_scalar_functions_fold scalarFunctionConstantsSql + sql "set debug_skip_fold_constant = true" + qt_scalar_functions_runtime scalarFunctionConstantsSql + sql "set debug_skip_fold_constant = false" + testFoldConst(scalarFunctionConstantsSql) + + qt_timezone_inputs """ + select + year(cast('2024-02-29 12:34:56.123456789+08:00' as timestamp_ns)), + year(cast('2024-02-29T04:34:56.123456789Z' as timestamp_ns)), + year(cast('2024-02-29 12:34:56.123456789' as timestamp_ns)), + seconds_add(cast('1969-12-31 23:59:59.999999999+08:00' as timestamp_ns), 1), + seconds_add(cast('1969-12-31T15:59:59.999999999Z' as timestamp_ns), 1), + seconds_add(cast('1969-12-31 23:59:59.999999999' as timestamp_ns), 1) + """ + + qt_nanosecond_boundaries """ + select + time(cast('1969-12-31 23:59:59.999999499' as timestamp_ns)), + time(cast('1969-12-31 23:59:59.999999500' as timestamp_ns)), + date_format(cast('1677-09-21 00:12:43.145224192' as timestamp_ns), + '%Y-%m-%d %H:%i:%s.%f'), + timediff(cast('1970-01-01 00:00:00.000000000' as timestamp_ns), + cast('1969-12-31 23:59:59.999999999' as timestamp_ns)), + microseconds_diff(cast('1970-01-01 00:00:00.000000000' as timestamp_ns), + cast('1969-12-31 23:59:59.999999999' as timestamp_ns)), + microseconds_add(cast('1969-12-31 23:59:59.999999500' as timestamp_ns), 1) + """ + + order_qt_extract_calendar """ + select id, + year(value), century(value), quarter(value), month(value), day(value), + dayofmonth(value), dayofweek(value), dayofyear(value), weekday(value), + week(value), week(value, 3), weekofyear(value), yearweek(value), yearweek(value, 3), + dayname(value), monthname(value) + from timestamp_ns_functions + order by id + """ + order_qt_extract_time """ + select id, + hour(value), minute(value), second(value), microsecond(value), + year_month(value), day_hour(value), day_minute(value), day_second(value), + day_microsecond(value), hour_minute(value), hour_second(value), + hour_microsecond(value), minute_second(value), minute_microsecond(value), + second_microsecond(value) + from timestamp_ns_functions + order by id + """ + order_qt_format_and_convert """ + select id, + date_format(value, '%Y-%m-%d %H:%i:%s.%f'), + time_format(value, '%H:%i:%s.%f'), + to_iso8601(value), + cast(to_json(value) as string), + date(value), datev2(value), to_date(value), to_datev2(value), + timestamp(value), time(value), + to_days(value), to_seconds(value), unix_timestamp(value), + second_timestamp(value), millisecond_timestamp(value), microsecond_timestamp(value), + last_day(value), to_monday(value) + from timestamp_ns_functions + order by id + """ + + order_qt_simple_add_sub """ + select id, + microseconds_add(value, 1), microseconds_sub(value, 1), + milliseconds_add(value, 1), milliseconds_sub(value, 1), + seconds_add(value, 1), seconds_sub(value, 1), + minutes_add(value, 1), minutes_sub(value, 1), + hours_add(value, 1), hours_sub(value, 1), + days_add(value, 1), days_sub(value, 1), + weeks_add(value, 1), weeks_sub(value, 1), + months_add(value, 1), months_sub(value, 1), + quarters_add(value, 1), quarters_sub(value, 1), + years_add(value, 1), years_sub(value, 1) + from timestamp_ns_functions + where id between 2 and 5 + order by id + """ + + order_qt_compound_add_sub """ + select id, + date_add(value, interval '1 02' day_hour), + date_sub(value, interval '1 02' day_hour), + date_add(value, interval '1 02:03' day_minute), + date_sub(value, interval '1 02:03' day_minute), + date_add(value, interval '1 02:03:04' day_second), + date_sub(value, interval '1 02:03:04' day_second), + date_add(value, interval '1 02:03:04.000005' day_microsecond), + date_sub(value, interval '1 02:03:04.000005' day_microsecond), + date_add(value, interval '2:03' hour_minute), + date_sub(value, interval '2:03' hour_minute), + date_add(value, interval '2:03:04' hour_second), + date_sub(value, interval '2:03:04' hour_second), + date_add(value, interval '2:03:04.000005' hour_microsecond), + date_sub(value, interval '2:03:04.000005' hour_microsecond), + date_add(value, interval '3:04' minute_second), + date_sub(value, interval '3:04' minute_second), + date_add(value, interval '3:04.000005' minute_microsecond), + date_sub(value, interval '3:04.000005' minute_microsecond), + date_add(value, interval '4.000005' second_microsecond), + date_sub(value, interval '4.000005' second_microsecond), + date_add(value, interval '1-2' year_month), + date_sub(value, interval '1-2' year_month) + from timestamp_ns_functions + where id = 5 + order by id + """ + + order_qt_add_time_sub_time """ + select id, + add_time(value, cast('01:02:03.123456' as time(6))), + sub_time(value, cast('01:02:03.123456' as time(6))) + from timestamp_ns_functions + where id between 2 and 5 + order by id + """ + + qt_diff_units """ + select + timediff( + cast('1970-01-01 00:00:01.123456789' as timestamp_ns), + cast('1969-12-31 23:59:59.999999999' as timestamp_ns)), + microseconds_diff( + cast('1970-01-01 00:00:00.000001999' as timestamp_ns), + cast('1970-01-01 00:00:00.000000000' as timestamp_ns)), + milliseconds_diff( + cast('1970-01-01 00:00:00.001999999' as timestamp_ns), + cast('1970-01-01 00:00:00.000000000' as timestamp_ns)), + seconds_diff( + cast('1970-01-01 00:00:01.999999999' as timestamp_ns), + cast('1970-01-01 00:00:00.000000000' as timestamp_ns)), + minutes_diff( + cast('1970-01-01 00:01:59.999999999' as timestamp_ns), + cast('1970-01-01 00:00:00.000000000' as timestamp_ns)), + hours_diff( + cast('1970-01-01 01:59:59.999999999' as timestamp_ns), + cast('1970-01-01 00:00:00.000000000' as timestamp_ns)), + days_diff(cast('2024-03-01 12:00:00.000000001' as timestamp_ns), + cast('2024-02-29 12:00:00.000000000' as timestamp_ns)), + weeks_diff(cast('2024-03-07 12:00:00.000000001' as timestamp_ns), + cast('2024-02-29 12:00:00.000000000' as timestamp_ns)), + months_diff(cast('2024-03-29 12:00:00.000000001' as timestamp_ns), + cast('2024-02-29 12:00:00.000000000' as timestamp_ns)), + quarters_diff(cast('2024-05-29 12:00:00.000000001' as timestamp_ns), + cast('2024-02-29 12:00:00.000000000' as timestamp_ns)), + years_diff(cast('2025-02-28 12:00:00.000000001' as timestamp_ns), + cast('2024-02-29 12:00:00.000000000' as timestamp_ns)), + datediff(cast('2024-03-01 00:00:00.000000001' as timestamp_ns), + cast('2024-02-29 23:59:59.999999999' as timestamp_ns)) + """ + + order_qt_trunc """ + select id, + date_trunc(value, 'year'), date_trunc(value, 'quarter'), + date_trunc(value, 'month'), date_trunc(value, 'week'), + date_trunc(value, 'day'), date_trunc(value, 'hour'), + date_trunc(value, 'minute'), date_trunc(value, 'second') + from timestamp_ns_functions + where id between 2 and 5 + order by id + """ + order_qt_floor """ + select id, + year_floor(value), quarter_floor(value), month_floor(value), week_floor(value), + day_floor(value), hour_floor(value), minute_floor(value), second_floor(value) + from timestamp_ns_functions + where id between 2 and 5 + order by id + """ + order_qt_ceil """ + select id, + year_ceil(value), quarter_ceil(value), month_ceil(value), week_ceil(value), + day_ceil(value), hour_ceil(value), minute_ceil(value), second_ceil(value) + from timestamp_ns_functions + where id between 2 and 5 + order by id + """ + qt_floor_ceil_period_origin """ + select + second_floor(cast('1970-01-01 00:00:02.123456789' as timestamp_ns), 2), + second_ceil(cast('1970-01-01 00:00:02.123456789' as timestamp_ns), 2), + second_floor( + cast('1970-01-01 00:00:02.123456789' as timestamp_ns), + cast('1970-01-01 00:00:00.500000000' as timestamp_ns)), + second_ceil( + cast('1970-01-01 00:00:02.123456789' as timestamp_ns), 2, + cast('1970-01-01 00:00:00.500000000' as timestamp_ns)) + """ + qt_date_floor_ceil_interval_constants """ + select + date_floor(cast('1969-12-31 23:59:59.999999999' as timestamp_ns), + interval 5 second), + date_ceil(cast('1969-12-31 23:59:59.999999999' as timestamp_ns), + interval 5 second), + date_floor(cast('2024-02-29 12:34:56.123456789' as timestamp_ns), + interval 3 minute), + date_ceil(cast('2024-02-29 12:34:56.123456789' as timestamp_ns), + interval 3 minute) + """ + order_qt_date_floor_ceil_interval_columns """ + select id, + date_floor(value, interval 5 second), + date_ceil(value, interval 5 second) + from timestamp_ns_functions + where id between 2 and 5 + order by id + """ + + qt_sequence_second """ + select sequence( + cast('1969-12-31 23:59:58.000000001' as timestamp_ns), + cast('1970-01-01 00:00:02.000000001' as timestamp_ns), + interval 1 second) + """ + qt_sequence_month """ + select sequence( + cast('2024-01-31 12:34:56.123456789' as timestamp_ns), + cast('2024-05-01 12:34:56.123456789' as timestamp_ns), + interval 1 month) + """ + qt_sequence_all_units """ + select + sequence(cast('2024-02-29 12:34:56.123456789' as timestamp_ns), + cast('2026-03-01 12:34:56.123456789' as timestamp_ns), interval 1 year), + sequence(cast('2024-02-29 12:34:56.123456789' as timestamp_ns), + cast('2024-12-01 12:34:56.123456789' as timestamp_ns), interval 1 quarter), + sequence(cast('2024-02-29 12:34:56.123456789' as timestamp_ns), + cast('2024-03-22 12:34:56.123456789' as timestamp_ns), interval 1 week), + sequence(cast('2024-02-29 12:34:56.123456789' as timestamp_ns), + cast('2024-03-03 12:34:56.123456789' as timestamp_ns), interval 1 day), + sequence(cast('2024-02-29 22:34:56.123456789' as timestamp_ns), + cast('2024-03-01 02:34:56.123456789' as timestamp_ns), interval 1 hour), + sequence(cast('1969-12-31 23:58:56.123456789' as timestamp_ns), + cast('1970-01-01 00:02:56.123456789' as timestamp_ns), interval 1 minute), + array_range(cast('1969-12-31 00:00:00.000000001' as timestamp_ns), + cast('1970-01-02 00:00:00.000000001' as timestamp_ns)) + """ + qt_convert_tz """ + select convert_tz(cast('2024-02-29 12:34:56.123456789' as timestamp_ns), + '+08:00', '+00:00') + """ + qt_comparison_helpers """ + select + least(cast('1969-12-31 23:59:59.999999999' as timestamp_ns), + cast('1970-01-01 00:00:00.000000001' as timestamp_ns)), + greatest(cast('1969-12-31 23:59:59.999999999' as timestamp_ns), + cast('1970-01-01 00:00:00.000000001' as timestamp_ns)), + field(cast('1970-01-01 00:00:00.000000001' as timestamp_ns), + cast('1969-12-31 23:59:59.999999999' as timestamp_ns), + cast('1970-01-01 00:00:00.000000001' as timestamp_ns)) + """ + qt_aggregate_helpers """ + select min(value), max(value), min_by(value, id), max_by(value, id) + from timestamp_ns_functions + """ + qt_additional_supported_aggregates """ + select + array_sort(array_agg(value)), + array_sort(collect_list(value)), + array_sort(collect_set(value)), + histogram(value), + topn_array(value, 3), + array_sort(map_keys(map_agg(value, id))), + array_sort(map_values(map_agg(id, value))) + from timestamp_ns_functions + where value is not null + """ + qt_event_aggregates """ + select + sequence_count('(?1)(?2)', value, id = 2, id = 3), + sequence_match('(?1)(?2)', value, id = 2, id = 3), + window_funnel(86400, 'default', value, id = 2, id = 3), + window_funnel_v2(86400, 'default', value, id = 2, id = 3), + topn_weighted(value, cast(id as bigint), 3) + from timestamp_ns_functions + """ + qt_array_and_map_functions """ + select + array_min(array( + cast('1677-09-21 00:12:43.145224192' as timestamp_ns), + cast('1970-01-01 00:00:00.000000000' as timestamp_ns), + cast('2262-04-11 23:47:16.854775807' as timestamp_ns))), + array_max(array( + cast('1677-09-21 00:12:43.145224192' as timestamp_ns), + cast('1970-01-01 00:00:00.000000000' as timestamp_ns), + cast('2262-04-11 23:47:16.854775807' as timestamp_ns))), + array_contains(array(value, cast('1970-01-01 00:00:00.000000000' as timestamp_ns)), + value), + array_position(array(cast('1970-01-01 00:00:00.000000000' as timestamp_ns), value), + value), + countequal(array(value, value), value), + map_contains_key(map(value, id), value), + map_contains_value(map(id, value), value), + map_contains_entry(map(id, value), id, value) + from timestamp_ns_functions + where id = 5 + """ + + sql "drop dictionary if exists timestamp_ns_function_dict" + sql """ + create dictionary timestamp_ns_function_dict using timestamp_ns_functions + ( + id KEY, + value VALUE + ) + LAYOUT(HASH_MAP) + properties('data_lifetime'='600') + """ + waitAllDictionariesReady() + qt_dictionary_functions """ + select + dict_get('${context.dbName}.timestamp_ns_function_dict', 'value', 1), + dict_get('${context.dbName}.timestamp_ns_function_dict', 'value', 3), + dict_get_many('${context.dbName}.timestamp_ns_function_dict', + ['value'], struct(5)) + """ + order_qt_window_functions """ + select id, + lag(value) over(order by id), + lead(value) over(order by id), + first_value(value) over(order by id rows between unbounded preceding and current row), + last_value(value) over(order by id rows between current row and unbounded following) + from timestamp_ns_functions + order by id + """ + + // Arithmetic and truncation never wrap across the signed epoch-nanosecond domain. + for (def boundarySql : [ + "select microseconds_sub(cast('1677-09-21 00:12:43.145224192' as timestamp_ns), 1)", + "select seconds_add(cast('2262-04-11 23:47:16.854775807' as timestamp_ns), 1)", + "select date_trunc(cast('1677-09-21 00:12:43.145224192' as timestamp_ns), 'second')", + "select second_floor(cast('1677-09-21 00:12:43.145224192' as timestamp_ns))", + "select second_ceil(cast('2262-04-11 23:47:16.854775807' as timestamp_ns))"]) { + test { + sql boundarySql + exception "out of range" + } + } + + for (def unsupportedSql : [ + "select array_sum(value) from timestamp_ns_functions", + "select bitmap_count(value) from timestamp_ns_functions"]) { + test { + sql unsupportedSql + exception "function" + } + } +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_generated_column.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_generated_column.groovy new file mode 100644 index 00000000000000..b973884c2073a8 --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_generated_column.groovy @@ -0,0 +1,41 @@ +// 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. + +suite("test_timestamp_ns_generated_column") { + sql "drop table if exists timestamp_ns_generated_column" + sql """ + create table timestamp_ns_generated_column ( + id int, + source_dt timestamp_ns, + generated_dt timestamp_ns generated always as (source_dt) + ) + duplicate key(id) + distributed by hash(id) buckets 1 + properties("replication_num" = "1") + """ + sql """ + insert into timestamp_ns_generated_column(id, source_dt) values + (1, '1677-09-21 00:12:43.145224192'), + (2, '1970-01-01 00:00:00.123456789'), + (3, '2262-04-11 23:47:16.854775807') + """ + order_qt_generated_column """ + select id, source_dt, generated_dt, source_dt = generated_dt + from timestamp_ns_generated_column + order by id + """ +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_group_by.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_group_by.groovy new file mode 100644 index 00000000000000..901a872a1493c2 --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_group_by.groovy @@ -0,0 +1,45 @@ +// 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. + +suite("test_timestamp_ns_group_by") { + sql "drop table if exists timestamp_ns_group_by" + sql """ + create table timestamp_ns_group_by ( + id int, + dt timestamp_ns + ) + duplicate key(id) + distributed by hash(id) buckets 2 + properties("replication_num" = "1") + """ + sql """ + insert into timestamp_ns_group_by values + (1, '1677-09-21 00:12:43.145224192'), + (2, '1970-01-01 00:00:00.000000000'), + (3, '1970-01-01 00:00:00.000000000'), + (4, '2262-04-11 23:47:16.854775807'), + (5, null), + (6, null) + """ + + order_qt_group_by """ + select dt, count(*), min(id), max(id) + from timestamp_ns_group_by + group by dt + order by dt nulls first + """ +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_index.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_index.groovy new file mode 100644 index 00000000000000..6a379cf0940d82 --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_index.groovy @@ -0,0 +1,53 @@ +// 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. + +suite("test_timestamp_ns_index") { + sql "drop table if exists timestamp_ns_index" + sql """ + create table timestamp_ns_index ( + id int, + dt timestamp_ns, + index idx_dt(dt) using inverted + ) + duplicate key(id) + distributed by hash(id) buckets 1 + properties( + "replication_num" = "1", + "bloom_filter_columns" = "dt" + ) + """ + sql """ + insert into timestamp_ns_index values + (1, '1677-09-21 00:12:43.145224192'), + (2, '1970-01-01 00:00:00.000000000'), + (3, '1970-01-01 00:00:00.000000001'), + (4, '2262-04-11 23:47:16.854775807') + """ + + order_qt_eq "select id, dt from timestamp_ns_index where dt = '1970-01-01 00:00:00.000000001' order by id" + order_qt_range """ + select id, dt from timestamp_ns_index + where dt >= '1970-01-01 00:00:00.000000000' + and dt <= '1970-01-01 00:00:00.000000001' + order by id + """ + order_qt_in """ + select id, dt from timestamp_ns_index + where dt in ('1677-09-21 00:12:43.145224192', '2262-04-11 23:47:16.854775807') + order by id + """ +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_join.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_join.groovy new file mode 100644 index 00000000000000..83a0aea14f01f0 --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_join.groovy @@ -0,0 +1,59 @@ +// 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. + +suite("test_timestamp_ns_join") { + sql "drop table if exists timestamp_ns_join_left" + sql "drop table if exists timestamp_ns_join_right" + for (def tableName : ["timestamp_ns_join_left", "timestamp_ns_join_right"]) { + sql """ + create table ${tableName} ( + id int, + dt timestamp_ns + ) + duplicate key(id) + distributed by hash(id) buckets 2 + properties("replication_num" = "1") + """ + } + sql """ + insert into timestamp_ns_join_left values + (1, '1677-09-21 00:12:43.145224192'), + (2, '1970-01-01 00:00:00.000000000'), + (3, '1970-01-01 00:00:00.000000001'), + (4, null) + """ + sql """ + insert into timestamp_ns_join_right values + (11, '1677-09-21 00:12:43.145224192'), + (12, '1970-01-01 00:00:00.000000001'), + (13, '2262-04-11 23:47:16.854775807'), + (14, null) + """ + + order_qt_inner_join """ + select l.id, l.dt, r.id + from timestamp_ns_join_left l + join timestamp_ns_join_right r on l.dt = r.dt + order by l.id, r.id + """ + order_qt_left_join """ + select l.id, l.dt, r.id + from timestamp_ns_join_left l + left join timestamp_ns_join_right r on l.dt = r.dt + order by l.id, r.id + """ +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_literal.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_literal.groovy new file mode 100644 index 00000000000000..2a771e2e4b73a0 --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_literal.groovy @@ -0,0 +1,151 @@ +// 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. + +suite("test_timestamp_ns_literal") { + qt_boundary_and_rounding """ + select + cast('1677-09-21 00:12:43.145224192' as timestamp_ns), + cast('1969-12-31 23:59:59.999999999' as timestamp_ns), + cast('1970-01-01 00:00:00.1234567894' as timestamp_ns), + cast('1970-01-01 00:00:00.1234567895' as timestamp_ns), + cast('1970-01-01 00:00:00.9999999995' as timestamp_ns), + cast('2262-04-11 23:47:16.854775807' as timestamp_ns) + """ + + sql "set debug_skip_fold_constant = true" + qt_boundary_and_rounding_without_fold """ + select + cast('1677-09-21 00:12:43.145224192' as timestamp_ns), + cast('1970-01-01 00:00:00.1234567895' as timestamp_ns), + cast('1970-01-01 00:00:00.9999999995' as timestamp_ns), + cast('2262-04-11 23:47:16.854775807' as timestamp_ns) + """ + sql "set debug_skip_fold_constant = false" + + qt_invalid_and_out_of_range """ + select + cast('1970-02-30 00:00:00.000000000' as timestamp_ns), + cast('1677-09-21 00:12:43.145224191' as timestamp_ns), + cast('2262-04-11 23:47:16.854775808' as timestamp_ns) + """ + + for (def invalidScale : [0, 1, 6, 7, 8, 9]) { + test { + sql "select cast('1970-01-01 00:00:00.000000001' as timestamp_ns(${invalidScale}))" + exception "timestamp_ns does not support precision" + } + + test { + sql """ + create table test_timestamp_ns_invalid_scale_${invalidScale} ( + id int, + dt timestamp_ns(${invalidScale}) + ) + distributed by hash(id) buckets 1 + properties("replication_num" = "1") + """ + exception "timestamp_ns does not support precision" + } + } + + for (def datetimeType : ["datetime", "datetimev2"]) { + for (def invalidScale : [7, 8, 9]) { + test { + sql "select cast('1970-01-01 00:00:00.123456789' as ${datetimeType}(${invalidScale}))" + exception "between 0 and 6" + } + } + } + + sql "drop table if exists test_timestamp_ns_literal_cast_input" + sql """ + create table test_timestamp_ns_literal_cast_input ( + id int, + value varchar(64) + ) + duplicate key(id) + distributed by hash(id) buckets 1 + properties("replication_num" = "1") + """ + sql """ + insert into test_timestamp_ns_literal_cast_input values + (1, '2024-01-01 00:00:00.123456789'), + (2, '2024-01-01 00:00:00.123.456') + """ + def originalEnableStrictCast = sql("select @@enable_strict_cast")[0][0] + try { + sql "set enable_strict_cast = false" + order_qt_nonconstant_permissive_cast """ + select id, cast(value as timestamp_ns) + from test_timestamp_ns_literal_cast_input + order by id + """ + + sql "set enable_strict_cast = true" + test { + sql """ + select cast(value as timestamp_ns) + from test_timestamp_ns_literal_cast_input + where id = 2 + """ + exception "2024-01-01 00:00:00.123.456" + } + } finally { + sql "set enable_strict_cast = ${originalEnableStrictCast}" + } + + qt_seconds_add "select seconds_add(cast('1970-01-01 00:00:00.000000001' as timestamp_ns), 1)" + + qt_current_timestamp_support """ + select + cast(current_timestamp as timestamp_ns) is not null, + cast(current_timestamp(6) as timestamp_ns) is not null + """ + + sql "drop table if exists test_timestamp_ns_current_default" + sql """ + create table test_timestamp_ns_current_default ( + id int, + dt_literal timestamp_ns default '1970-01-01 00:00:00.000000001', + dt_current timestamp_ns default current_timestamp, + dt_current_6 timestamp_ns default current_timestamp(6), + dt_current_9 timestamp_ns default current_timestamp(9) + ) + distributed by hash(id) buckets 1 + properties("replication_num" = "1") + """ + sql "insert into test_timestamp_ns_current_default(id) values (1)" + sql "insert into test_timestamp_ns_current_default values (2, default, default, default, default)" + order_qt_timestamp_ns_defaults """ + select + id, + dt_literal, + dt_current is not null, + dt_current_6 is not null, + dt_current_9 is not null, + dt_current between seconds_sub(cast(current_timestamp as timestamp_ns), 3600) + and cast(current_timestamp as timestamp_ns), + right(cast(dt_current_6 as string), 3) = '000' + from test_timestamp_ns_current_default + order by id + """ + + test { + sql "create table test_timestamp_ns_invalid_current_default (id int, ts timestamp_ns default current_timestamp(10)) distributed by hash(id) buckets 1 properties('replication_num'='1')" + exception "precision" + } +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_mv.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_mv.groovy new file mode 100644 index 00000000000000..6d259178c8871f --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_mv.groovy @@ -0,0 +1,77 @@ +// 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. + +suite("test_timestamp_ns_mv") { + sql "drop table if exists timestamp_ns_mv_probe" + sql "drop table if exists timestamp_ns_mv_build" + for (def tableName : ["timestamp_ns_mv_probe", "timestamp_ns_mv_build"]) { + sql """ + create table ${tableName} ( + id int, + dt timestamp_ns + ) + duplicate key(id) + distributed by hash(id) buckets 2 + properties("replication_num" = "1") + """ + } + sql """ + insert into timestamp_ns_mv_probe values + (1, '1677-09-21 00:12:43.145224192'), + (2, '1970-01-01 00:00:00.000000000'), + (3, '1970-01-01 00:00:00.000000000'), + (4, '2262-04-11 23:47:16.854775807'), + (5, null) + """ + sql """ + insert into timestamp_ns_mv_build values + (11, '1677-09-21 00:12:43.145224192'), + (12, '2262-04-11 23:47:16.854775807') + """ + + sql "drop materialized view if exists timestamp_ns_sync_mv on timestamp_ns_mv_probe" + create_sync_mv(context.dbName, "timestamp_ns_mv_probe", "timestamp_ns_sync_mv", """ + select dt as mv_dt, count(*) as row_count + from timestamp_ns_mv_probe + group by dt + """) + order_qt_sync_mv """ + select dt, count(*) + from timestamp_ns_mv_probe + group by dt + order by dt nulls first + """ + + sql "drop materialized view if exists timestamp_ns_multi_mv" + sql """ + create materialized view timestamp_ns_multi_mv + build deferred refresh complete on manual + distributed by hash(probe_id) buckets 1 + properties("replication_num" = "1") + as + select p.id as probe_id, p.dt, b.id as build_id + from timestamp_ns_mv_probe p + join timestamp_ns_mv_build b on p.dt = b.dt + """ + sql "refresh materialized view timestamp_ns_multi_mv complete" + waitingMTMVTaskFinishedByMvName("timestamp_ns_multi_mv") + order_qt_multi_table_mv """ + select probe_id, dt, build_id + from timestamp_ns_multi_mv + order by probe_id, build_id + """ +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_partition_bucket.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_partition_bucket.groovy new file mode 100644 index 00000000000000..12c22b527d4ac7 --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_partition_bucket.groovy @@ -0,0 +1,125 @@ +// 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. + +suite("test_timestamp_ns_partition_bucket") { + sql "drop table if exists timestamp_ns_partition_bucket" + sql """ + create table timestamp_ns_partition_bucket ( + dt timestamp_ns, + id int + ) + duplicate key(dt) + partition by range(dt) ( + partition p_before_epoch values less than ('1970-01-01 00:00:00.000000000'), + partition p_epoch values less than ('1970-01-01 00:00:00.000000002'), + partition p_after_epoch values less than MAXVALUE + ) + distributed by hash(dt) buckets 4 + properties("replication_num" = "1") + """ + sql """ + insert into timestamp_ns_partition_bucket values + ('1677-09-21 00:12:43.145224192', 1), + ('1969-12-31 23:59:59.999999999', 2), + ('1970-01-01 00:00:00.000000000', 3), + ('1970-01-01 00:00:00.000000001', 4), + ('1970-01-01 00:00:00.123456789', 5), + ('2262-04-11 23:47:16.854775807', 6), + (null, 7) + """ + + sql "set debug_skip_fold_constant = false" + explain { + sql """ + select * from timestamp_ns_partition_bucket + where dt = cast('1970-01-01 00:00:00.000000000' as timestamp_ns) + """ + contains "partitions=1/3 (p_epoch)" + contains "tablets=1/4" + } + explain { + sql """ + select * from timestamp_ns_partition_bucket + where dt >= cast('2262-04-11 23:47:16.854775807' as timestamp_ns) + """ + contains "partitions=1/3 (p_after_epoch)" + } + explain { + sql "select * from timestamp_ns_partition_bucket where dt is null" + contains "partitions=1/3 (p_before_epoch)" + } + explain { + sql """ + select * from timestamp_ns_partition_bucket + where date(dt) in (date '1969-12-31') + """ + contains "partitions=1/3 (p_before_epoch)" + } + + sql "set debug_skip_fold_constant = true" + explain { + sql """ + select * from timestamp_ns_partition_bucket + where dt = cast('1970-01-01 00:00:00.000000000' as timestamp_ns) + """ + contains "partitions=1/3 (p_epoch)" + contains "tablets=4/4" + } + sql "set debug_skip_fold_constant = false" + + sql "set experimental_enable_virtual_slot_for_cse = true" + explain { + sql """ + verbose select date_trunc(dt, 'second') + from timestamp_ns_partition_bucket + where date_trunc(dt, 'second') >= cast('1970-01-01 00:00:00' as timestamp_ns) + and date_trunc(dt, 'second') < cast('1970-01-02 00:00:00' as timestamp_ns) + """ + contains "__DORIS_VIRTUAL_COL__" + contains "type=timestamp_ns" + contains "date_trunc" + } + sql "set experimental_enable_virtual_slot_for_cse = false" + + order_qt_partition_rows "select id, dt from timestamp_ns_partition_bucket order by id" + order_qt_nullable_first_range """ + select id, dt from timestamp_ns_partition_bucket where dt is null order by id + """ + + sql "drop table if exists timestamp_ns_list_partition_rounding" + sql """ + create table timestamp_ns_list_partition_rounding ( + dt timestamp_ns, + id int + ) + duplicate key(dt) + partition by list(dt) ( + partition p_round values in ('1970-01-01 00:00:00.1234567895'), + partition p_carry values in ('1970-01-01 00:00:00.9999999995') + ) + distributed by hash(id) buckets 1 + properties("replication_num" = "1") + """ + sql """ + insert into timestamp_ns_list_partition_rounding values + ('1970-01-01 00:00:00.1234567895', 1), + ('1970-01-01 00:00:00.9999999995', 2) + """ + order_qt_list_partition_rounding """ + select dt, id from timestamp_ns_list_partition_rounding order by id + """ +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_primary_key.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_primary_key.groovy new file mode 100644 index 00000000000000..3e5bbe31998998 --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_primary_key.groovy @@ -0,0 +1,89 @@ +// 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. + +suite("test_timestamp_ns_primary_key") { + sql "drop table if exists timestamp_ns_primary_key" + sql """ + create table timestamp_ns_primary_key ( + dt timestamp_ns not null, + id int not null, + value varchar(16) + ) + unique key(dt, id) + distributed by hash(dt) buckets 2 + properties( + "replication_num" = "1", + "enable_unique_key_merge_on_write" = "true" + ) + """ + sql """ + alter table timestamp_ns_primary_key + add constraint timestamp_ns_primary_key_constraint primary key(dt, id) + """ + sql """ + insert into timestamp_ns_primary_key values + ('1677-09-21 00:12:43.145224192', 1, 'minimum'), + ('1969-12-31 23:59:59.999999999', 2, 'before'), + ('1970-01-01 00:00:00.000000000', 3, 'epoch'), + ('1970-01-01 00:00:00.000000001', 4, 'after'), + ('2262-04-11 23:47:16.854775807', 5, 'maximum') + """ + + order_qt_key_range_scan """ + select dt, id, value + from timestamp_ns_primary_key + where dt >= '1969-12-31 23:59:59.999999999' + and dt < '1970-01-01 00:00:00.000000001' + order by dt, id + """ + order_qt_full_key_lookup """ + select dt, id, value + from timestamp_ns_primary_key + where dt = '1970-01-01 00:00:00.000000001' and id = 4 + order by dt, id + """ + + sql "drop table if exists timestamp_ns_sequence_type" + sql """ + create table timestamp_ns_sequence_type ( + id int not null, + value varchar(16) + ) + unique key(id) + distributed by hash(id) buckets 1 + properties( + "replication_num" = "1", + "enable_unique_key_merge_on_write" = "true", + "function_column.sequence_type" = "timestamp_ns" + ) + """ + sql """ + insert into timestamp_ns_sequence_type(id, value, __DORIS_SEQUENCE_COL__) values + (1, 'newer', '1970-01-01 00:00:00.000000001'), + (2, 'minimum', '1677-09-21 00:12:43.145224192') + """ + sql """ + insert into timestamp_ns_sequence_type(id, value, __DORIS_SEQUENCE_COL__) values + (1, 'older', '1970-01-01 00:00:00.000000000'), + (2, 'maximum', '2262-04-11 23:47:16.854775807') + """ + order_qt_timestamp_ns_sequence_type """ + select id, value, __DORIS_SEQUENCE_COL__ + from timestamp_ns_sequence_type + order by id + """ +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_rf.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_rf.groovy new file mode 100644 index 00000000000000..b773cb0a5b2c72 --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_rf.groovy @@ -0,0 +1,103 @@ +// 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. + +suite("test_timestamp_ns_rf") { + sql "drop table if exists timestamp_ns_rf_probe" + sql "drop table if exists timestamp_ns_rf_build" + for (def tableName : ["timestamp_ns_rf_probe", "timestamp_ns_rf_build"]) { + sql """ + create table ${tableName} ( + id int, + dt timestamp_ns + ) + duplicate key(id) + distributed by hash(id) buckets 4 + properties("replication_num" = "1") + """ + } + sql """ + insert into timestamp_ns_rf_probe values + (1, '1677-09-21 00:12:43.145224192'), + (2, '1969-12-31 23:59:59.999999999'), + (3, '1970-01-01 00:00:00.000000000'), + (4, '1970-01-01 00:00:00.000000001'), + (5, '2262-04-11 23:47:16.854775807'), + (6, null) + """ + sql """ + insert into timestamp_ns_rf_build values + (11, '1677-09-21 00:12:43.145224192'), + (12, '1970-01-01 00:00:00.000000001'), + (13, '2262-04-11 23:47:16.854775807') + """ + + def originalEnableRuntimeFilterPrune = sql("select @@enable_runtime_filter_prune")[0][0] + def originalRuntimeFilterType = sql("select @@runtime_filter_type")[0][0] + try { + sql "set enable_runtime_filter_prune = false" + sql "set runtime_filter_type = 1" + explain { + sql """ + verbose select p.id, b.id + from timestamp_ns_rf_probe p + join timestamp_ns_rf_build b on p.dt = b.dt + """ + contains "runtime filters: RF000[in]" + } + order_qt_runtime_filter_in """ + select p.id, p.dt, b.id + from timestamp_ns_rf_probe p + join timestamp_ns_rf_build b on p.dt = b.dt + order by p.id, b.id + """ + + sql "set runtime_filter_type = 2" + explain { + sql """ + verbose select p.id, b.id + from timestamp_ns_rf_probe p + join timestamp_ns_rf_build b on p.dt = b.dt + """ + contains "runtime filters: RF000[bloom]" + } + order_qt_runtime_filter_bloom """ + select p.id, p.dt, b.id + from timestamp_ns_rf_probe p + join timestamp_ns_rf_build b on p.dt = b.dt + order by p.id, b.id + """ + + sql "set runtime_filter_type = 4" + explain { + sql """ + verbose select p.id, b.id + from timestamp_ns_rf_probe p + join timestamp_ns_rf_build b on p.dt = b.dt + """ + contains "runtime filters: RF000[min_max]" + } + order_qt_runtime_filter_min_max """ + select p.id, p.dt, b.id + from timestamp_ns_rf_probe p + join timestamp_ns_rf_build b on p.dt = b.dt + order by p.id, b.id + """ + } finally { + sql "set runtime_filter_type = '${originalRuntimeFilterType}'" + sql "set enable_runtime_filter_prune = ${originalEnableRuntimeFilterPrune}" + } +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_sort.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_sort.groovy new file mode 100644 index 00000000000000..13b365b3c8d244 --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_sort.groovy @@ -0,0 +1,45 @@ +// 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. + +suite("test_timestamp_ns_sort") { + sql "drop table if exists timestamp_ns_sort" + sql """ + create table timestamp_ns_sort ( + id int, + dt timestamp_ns + ) + duplicate key(id) + distributed by hash(id) buckets 4 + properties("replication_num" = "1") + """ + sql """ + insert into timestamp_ns_sort values + (1, '2262-04-11 23:47:16.854775807'), + (2, '1970-01-01 00:00:00.000000001'), + (3, null), + (4, '1677-09-21 00:12:43.145224192'), + (5, '1970-01-01 00:00:00.000000000'), + (6, '1969-12-31 23:59:59.999999999') + """ + + order_qt_asc "select id, dt from timestamp_ns_sort order by dt asc nulls first, id" + order_qt_desc "select id, dt from timestamp_ns_sort order by dt desc nulls last, id" + order_qt_topn "select id, dt from timestamp_ns_sort order by dt asc nulls last, id limit 3" + order_qt_topn_offset """ + select id, dt from timestamp_ns_sort order by dt desc nulls first, id limit 2 offset 2 + """ +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_storage_agg_key.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_storage_agg_key.groovy new file mode 100644 index 00000000000000..b35fb0ad9ee118 --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_storage_agg_key.groovy @@ -0,0 +1,57 @@ +// 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. + +suite("test_timestamp_ns_storage_agg_key") { + sql "drop table if exists timestamp_ns_storage_agg_key" + sql """ + create table timestamp_ns_storage_agg_key ( + dt timestamp_ns, + max_dt timestamp_ns max, + min_dt timestamp_ns min, + amount bigint sum + ) + aggregate key(dt) + distributed by hash(dt) buckets 2 + properties("replication_num" = "1") + """ + sql """ + insert into timestamp_ns_storage_agg_key values + ('1677-09-21 00:12:43.145224192', '1677-09-21 00:12:43.145224192', '1677-09-21 00:12:43.145224200', 1), + ('1970-01-01 00:00:00.000000000', '1970-01-01 00:00:00.000000001', '1969-12-31 23:59:59.999999999', 2), + ('1970-01-01 00:00:00.000000000', '2262-04-11 23:47:16.854775807', '1970-01-01 00:00:00.000000000', 3), + ('2262-04-11 23:47:16.854775807', '2262-04-11 23:47:16.854775807', '2262-04-11 23:47:16.854775800', 4) + """ + + order_qt_all "select dt, max_dt, min_dt, amount from timestamp_ns_storage_agg_key order by dt" + order_qt_eq "select dt, amount from timestamp_ns_storage_agg_key where dt = '1970-01-01 00:00:00.000000000' order by dt" + order_qt_ne "select dt, amount from timestamp_ns_storage_agg_key where dt != '1970-01-01 00:00:00.000000000' order by dt" + order_qt_gt "select dt, amount from timestamp_ns_storage_agg_key where dt > '1970-01-01 00:00:00.000000000' order by dt" + order_qt_ge "select dt, amount from timestamp_ns_storage_agg_key where dt >= '1970-01-01 00:00:00.000000000' order by dt" + order_qt_lt "select dt, amount from timestamp_ns_storage_agg_key where dt < '1970-01-01 00:00:00.000000000' order by dt" + order_qt_le "select dt, amount from timestamp_ns_storage_agg_key where dt <= '1970-01-01 00:00:00.000000000' order by dt" + order_qt_in """ + select dt, amount from timestamp_ns_storage_agg_key + where dt in ('1677-09-21 00:12:43.145224192', '2262-04-11 23:47:16.854775807') + order by dt + """ + order_qt_not_in """ + select dt, amount from timestamp_ns_storage_agg_key + where dt not in ('1677-09-21 00:12:43.145224192', '2262-04-11 23:47:16.854775807') + order by dt + """ + order_qt_is_not_null "select dt from timestamp_ns_storage_agg_key where dt is not null order by dt" +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_storage_dup_key.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_storage_dup_key.groovy new file mode 100644 index 00000000000000..055968306d8a90 --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_storage_dup_key.groovy @@ -0,0 +1,119 @@ +// 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. + +suite("test_timestamp_ns_storage_dup_key") { + sql "drop table if exists timestamp_ns_storage_dup_key" + sql """ + create table timestamp_ns_storage_dup_key ( + dt timestamp_ns, + value_dt timestamp_ns, + id int + ) + duplicate key(dt) + distributed by hash(dt) buckets 4 + properties("replication_num" = "1") + """ + sql """ + insert into timestamp_ns_storage_dup_key values + ('1677-09-21 00:12:43.145224192', '1677-09-21 00:12:43.145224200', 1), + ('1969-12-31 23:59:59.999999999', '1969-12-31 23:59:59.999999990', 2), + ('1970-01-01 00:00:00.000000000', '1970-01-01 00:00:00.000000000', 3), + ('1970-01-01 00:00:00.000000001', '1970-01-01 00:00:00.123456789', 4), + ('2262-04-11 23:47:16.854775807', '2262-04-11 23:47:16.854775800', 5), + (null, null, 6) + """ + + order_qt_all "select dt, value_dt, id from timestamp_ns_storage_dup_key order by id" + order_qt_eq "select id from timestamp_ns_storage_dup_key where dt = '1970-01-01 00:00:00.000000000' order by id" + order_qt_ne "select id from timestamp_ns_storage_dup_key where dt != '1970-01-01 00:00:00.000000000' order by id" + order_qt_gt "select id from timestamp_ns_storage_dup_key where dt > '1970-01-01 00:00:00.000000000' order by id" + order_qt_ge "select id from timestamp_ns_storage_dup_key where dt >= '1970-01-01 00:00:00.000000000' order by id" + order_qt_lt "select id from timestamp_ns_storage_dup_key where dt < '1970-01-01 00:00:00.000000000' order by id" + order_qt_le "select id from timestamp_ns_storage_dup_key where dt <= '1970-01-01 00:00:00.000000000' order by id" + order_qt_in """ + select id from timestamp_ns_storage_dup_key + where dt in ('1677-09-21 00:12:43.145224192', '2262-04-11 23:47:16.854775807') + order by id + """ + order_qt_not_in """ + select id from timestamp_ns_storage_dup_key + where dt not in ('1677-09-21 00:12:43.145224192', '2262-04-11 23:47:16.854775807') + order by id + """ + order_qt_is_null "select id from timestamp_ns_storage_dup_key where dt is null order by id" + order_qt_is_not_null "select id from timestamp_ns_storage_dup_key where dt is not null order by id" + qt_min_max_count "select min(dt), max(dt), count(dt) from timestamp_ns_storage_dup_key" + order_qt_cast_datetimev2_6 """ + select id, cast(dt as datetimev2(6)) + from timestamp_ns_storage_dup_key + order by id + """ + + sql "drop table if exists timestamp_ns_storage_dup_key_row_store" + sql """ + create table timestamp_ns_storage_dup_key_row_store ( + id int, + dt timestamp_ns + ) + duplicate key(id) + distributed by hash(id) buckets 1 + properties( + "replication_num" = "1", + "store_row_column" = "true" + ) + """ + sql """ + insert into timestamp_ns_storage_dup_key_row_store values + (1, '1677-09-21 00:12:43.145224192'), + (2, '1970-01-01 00:00:00.123456789'), + (3, '2262-04-11 23:47:16.854775807') + """ + order_qt_row_store "select id, dt from timestamp_ns_storage_dup_key_row_store order by id" + + sql """ + alter table timestamp_ns_storage_dup_key + add column schema_change_dt timestamp_ns + default '1970-01-01 00:00:00.000000001' after id + """ + waitForSchemaChangeDone { + sql """ + show alter table column + where TableName = 'timestamp_ns_storage_dup_key' + order by CreateTime desc limit 1 + """ + time 600 + } + order_qt_schema_change_default """ + select id, schema_change_dt + from timestamp_ns_storage_dup_key + where id in (1, 3, 6) + order by id + """ + + sql """ + insert into timestamp_ns_storage_dup_key values + ('1970-02-30 00:00:00.000000000', '1970-02-30 00:00:00.000000000', 100, default), + ('1677-09-21 00:12:43.145224191', '1677-09-21 00:12:43.145224191', 101, default), + ('2262-04-11 23:47:16.854775808', '2262-04-11 23:47:16.854775808', 102, default) + """ + order_qt_invalid_values """ + select id, dt, value_dt + from timestamp_ns_storage_dup_key + where id between 100 and 102 + order by id + """ +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_storage_uniq_key.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_storage_uniq_key.groovy new file mode 100644 index 00000000000000..e310464c3bece0 --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_storage_uniq_key.groovy @@ -0,0 +1,63 @@ +// 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. + +suite("test_timestamp_ns_storage_uniq_key") { + sql "drop table if exists timestamp_ns_storage_uniq_key" + sql """ + create table timestamp_ns_storage_uniq_key ( + dt timestamp_ns, + value_dt timestamp_ns, + value int + ) + unique key(dt) + distributed by hash(dt) buckets 2 + properties( + "replication_num" = "1", + "enable_unique_key_merge_on_write" = "true" + ) + """ + sql """ + insert into timestamp_ns_storage_uniq_key values + ('1677-09-21 00:12:43.145224192', '1677-09-21 00:12:43.145224200', 1), + ('1969-12-31 23:59:59.999999999', '1969-12-31 23:59:59.999999990', 2), + ('1970-01-01 00:00:00.000000000', '1970-01-01 00:00:00.000000000', 3), + ('1970-01-01 00:00:00.000000001', '1970-01-01 00:00:00.123456789', 4), + ('2262-04-11 23:47:16.854775807', '2262-04-11 23:47:16.854775800', 5) + """ + sql """ + insert into timestamp_ns_storage_uniq_key values + ('1970-01-01 00:00:00.000000000', '1970-01-01 00:00:00.000000001', 30) + """ + + order_qt_all "select dt, value_dt, value from timestamp_ns_storage_uniq_key order by dt" + order_qt_eq "select value from timestamp_ns_storage_uniq_key where dt = '1970-01-01 00:00:00.000000000' order by value" + order_qt_ne "select value from timestamp_ns_storage_uniq_key where dt != '1970-01-01 00:00:00.000000000' order by value" + order_qt_gt "select value from timestamp_ns_storage_uniq_key where dt > '1970-01-01 00:00:00.000000000' order by value" + order_qt_ge "select value from timestamp_ns_storage_uniq_key where dt >= '1970-01-01 00:00:00.000000000' order by value" + order_qt_lt "select value from timestamp_ns_storage_uniq_key where dt < '1970-01-01 00:00:00.000000000' order by value" + order_qt_le "select value from timestamp_ns_storage_uniq_key where dt <= '1970-01-01 00:00:00.000000000' order by value" + order_qt_in """ + select value from timestamp_ns_storage_uniq_key + where dt in ('1677-09-21 00:12:43.145224192', '2262-04-11 23:47:16.854775807') + order by value + """ + order_qt_not_in """ + select value from timestamp_ns_storage_uniq_key + where dt not in ('1677-09-21 00:12:43.145224192', '2262-04-11 23:47:16.854775807') + order by value + """ +} diff --git a/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_stream_load.groovy b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_stream_load.groovy new file mode 100644 index 00000000000000..1af8f42538466a --- /dev/null +++ b/regression-test/suites/datatype_p0/timestamp_ns/test_timestamp_ns_stream_load.groovy @@ -0,0 +1,75 @@ +// 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. + +suite("test_timestamp_ns_stream_load") { + sql "set time_zone = '+08:00'" + sql "drop table if exists test_timestamp_ns_stream_load" + sql """ + create table test_timestamp_ns_stream_load ( + id int, + dt timestamp_ns + ) + duplicate key(id) + distributed by hash(id) buckets 1 + properties("replication_num" = "1") + """ + + streamLoad { + table "test_timestamp_ns_stream_load" + file "test_timestamp_ns_stream_load.csv" + set "column_separator", "|" + set "strict_mode", "true" + set "max_filter_ratio", "0.3" + + check { result, exception, startTime, endTime -> + if (exception != null) { + throw exception + } + def json = parseJson(result) + assertEquals("success", json.Status.toLowerCase()) + assertEquals(9, json.NumberTotalRows) + assertEquals(7, json.NumberLoadedRows) + assertEquals(2, json.NumberFilteredRows) + } + } + + order_qt_stream_load """ + select id, dt + from test_timestamp_ns_stream_load + order by id + """ + + sql "drop table if exists test_timestamp_ns_insert_select" + sql """ + create table test_timestamp_ns_insert_select ( + id int, + dt timestamp_ns + ) + duplicate key(id) + distributed by hash(id) buckets 1 + properties("replication_num" = "1") + """ + sql """ + insert into test_timestamp_ns_insert_select + select id, dt from test_timestamp_ns_stream_load + """ + order_qt_insert_select """ + select id, dt + from test_timestamp_ns_insert_select + order by id + """ +} diff --git a/regression-test/suites/ddl_p0/test_current_timestamp_as_column_default_value.groovy b/regression-test/suites/ddl_p0/test_current_timestamp_as_column_default_value.groovy index 076b7a48fa113f..d07b54455a1a84 100644 --- a/regression-test/suites/ddl_p0/test_current_timestamp_as_column_default_value.groovy +++ b/regression-test/suites/ddl_p0/test_current_timestamp_as_column_default_value.groovy @@ -22,22 +22,22 @@ suite("test_current_timestamp_as_column_default_value") { test { sql """create table test_default10(a int, b varchar(100) default current_timestamp) distributed by hash(a) properties('replication_num'="1");""" - exception "Types other than DATETIME and DATETIMEV2 cannot use current_timestamp as the default value" + exception "Types other than DATETIME, DATETIMEV2, TIMESTAMP_NS and TIMESTAMPTZ cannot use current_timestamp" } test{ sql """alter table test_default4 add column dt varchar(100) default current_timestamp""" - exception "Types other than DATETIME and DATETIMEV2 cannot use current_timestamp as the default value" + exception "Types other than DATETIME, DATETIMEV2, TIMESTAMP_NS and TIMESTAMPTZ cannot use current_timestamp" } test { sql """create table test_default10(a int, b varchar(100) default current_timestamp) distributed by hash(a) properties('replication_num'="1");""" - exception "Types other than DATETIME and DATETIMEV2 cannot use current_timestamp as the default value" + exception "Types other than DATETIME, DATETIMEV2, TIMESTAMP_NS and TIMESTAMPTZ cannot use current_timestamp" } test{ sql "alter table test_default4 add column dt varchar(100) default current_timestamp" - exception "Types other than DATETIME and DATETIMEV2 cannot use current_timestamp as the default value" + exception "Types other than DATETIME, DATETIMEV2, TIMESTAMP_NS and TIMESTAMPTZ cannot use current_timestamp" } } diff --git a/regression-test/suites/nereids_function_p0/agg_function/agg.groovy b/regression-test/suites/nereids_function_p0/agg_function/agg.groovy index 6ac820aa47a917..bb60c371b07384 100644 --- a/regression-test/suites/nereids_function_p0/agg_function/agg.groovy +++ b/regression-test/suites/nereids_function_p0/agg_function/agg.groovy @@ -3214,4 +3214,102 @@ suite("nereids_agg_fn") { qt_sql_array_agg_not_nullable ''' select id,array_agg(kint) from fn_test_not_nullable group by id order by id''' + // TIMESTAMP_NS coverage mirrors the DATETIMEV2 aggregate-function matrix. + sql ''' + select histogram(cast(kdtmv2s1 as timestamp_ns)) from fn_test group by kbool order by kbool''' + sql ''' + select histogram(cast(kdtmv2s1 as timestamp_ns)) from fn_test''' + sql ''' + select count(id), histogram(cast(kdtmv2s1 as timestamp_ns)) from fn_test group by id order by id''' + sql ''' + select count(distinct id), histogram(cast(kdtmv2s1 as timestamp_ns)) from fn_test''' + sql ''' + select count(distinct id, kint), histogram(cast(kdtmv2s1 as timestamp_ns)) from fn_test group by kbool order by kbool''' + sql ''' + select count(distinct id), histogram(cast(kdtmv2s1 as timestamp_ns)) from fn_test''' + sql ''' + select histogram(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable group by kbool order by kbool''' + sql ''' + select histogram(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable''' + sql ''' + select count(id), histogram(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable group by id order by id''' + sql ''' + select count(distinct id), histogram(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable''' + sql ''' + select count(distinct id, kint), histogram(cast(kdtmv2s1 as timestamp_ns)) from fn_test group by kbool order by kbool''' + sql ''' + select count(distinct id), histogram(cast(kdtmv2s1 as timestamp_ns)) from fn_test''' + qt_sql_sequence_count_String_TimestampNs_Boolean_gb ''' + select sequence_count('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 5) from fn_test group by kbool order by kbool''' + qt_sql_sequence_count_String_TimestampNs_Boolean ''' + select sequence_count('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 5) from fn_test''' + qt_sql_sequence_count_String_TimestampNs_Boolean_agg_phase_1 ''' + select count(id), sequence_count('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 5) from fn_test group by id order by id''' + qt_sql_sequence_count_String_TimestampNs_Boolean_agg_phase_2 ''' + select count(distinct id), sequence_count('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 5) from fn_test''' + qt_sql_sequence_count_String_TimestampNs_Boolean_agg_phase_3 ''' + select count(distinct id, kint), sequence_count('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 5) from fn_test group by kbool order by kbool''' + qt_sql_sequence_count_String_TimestampNs_Boolean_agg_phase_4 ''' + select count(distinct id), sequence_count('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 5) from fn_test''' + qt_sql_sequence_count_String_TimestampNs_Boolean_gb_notnull ''' + select sequence_count('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 5) from fn_test_not_nullable group by kbool order by kbool''' + qt_sql_sequence_count_String_TimestampNs_Boolean_notnull ''' + select sequence_count('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 5) from fn_test_not_nullable''' + qt_sql_sequence_count_String_TimestampNs_Boolean_agg_phase_1_notnull ''' + select count(id), sequence_count('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 5) from fn_test_not_nullable group by id order by id''' + qt_sql_sequence_count_String_TimestampNs_Boolean_agg_phase_2_notnull ''' + select count(distinct id), sequence_count('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 5) from fn_test_not_nullable''' + qt_sql_sequence_count_String_TimestampNs_Boolean_agg_phase_3_notnull ''' + select count(distinct id, kint), sequence_count('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 5) from fn_test group by kbool order by kbool''' + qt_sql_sequence_count_String_TimestampNs_Boolean_agg_phase_4_notnull ''' + select count(distinct id), sequence_count('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 5) from fn_test''' + qt_sql_sequence_match_String_TimestampNs_Boolean_gb ''' + select sequence_match('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test group by kbool order by kbool''' + qt_sql_sequence_match_String_TimestampNs_Boolean ''' + select sequence_match('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test''' + qt_sql_sequence_match_String_TimestampNs_Boolean_agg_phase_1 ''' + select count(id), sequence_match('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test group by id order by id''' + qt_sql_sequence_match_String_TimestampNs_Boolean_agg_phase_2 ''' + select count(distinct id), sequence_match('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test''' + qt_sql_sequence_match_String_TimestampNs_Boolean_agg_phase_3 ''' + select count(distinct id, kint), sequence_match('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test group by kbool order by kbool''' + qt_sql_sequence_match_String_TimestampNs_Boolean_agg_phase_4 ''' + select count(distinct id), sequence_match('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test''' + qt_sql_sequence_match_String_TimestampNs_Boolean_gb_notnull ''' + select sequence_match('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test_not_nullable group by kbool order by kbool''' + qt_sql_sequence_match_String_TimestampNs_Boolean_notnull ''' + select sequence_match('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test_not_nullable''' + qt_sql_sequence_match_String_TimestampNs_Boolean_agg_phase_1_notnull ''' + select count(id), sequence_match('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test_not_nullable group by id order by id''' + qt_sql_sequence_match_String_TimestampNs_Boolean_agg_phase_2_notnull ''' + select count(distinct id), sequence_match('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test_not_nullable''' + qt_sql_sequence_match_String_TimestampNs_Boolean_agg_phase_3_notnull ''' + select count(distinct id, kint), sequence_match('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test group by kbool order by kbool''' + qt_sql_sequence_match_String_TimestampNs_Boolean_agg_phase_4_notnull ''' + select count(distinct id), sequence_match('(?1)(?2)', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test''' + qt_sql_window_funnel_BigInt_String_TimestampNs_Boolean_gb ''' + select window_funnel(3600 * 3, 'default', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test group by kbool order by kbool''' + qt_sql_window_funnel_BigInt_String_TimestampNs_Boolean ''' + select window_funnel(3600 * 3, 'default', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test''' + qt_sql_window_funnel_BigInt_String_TimestampNs_Boolean_agg_phase_1 ''' + select count(id), window_funnel(3600 * 3, 'default', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test group by id order by id''' + qt_sql_window_funnel_BigInt_String_TimestampNs_Boolean_agg_phase_2 ''' + select count(distinct id), window_funnel(3600 * 3, 'default', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test''' + qt_sql_window_funnel_BigInt_String_TimestampNs_Boolean_agg_phase_3 ''' + select count(distinct id, kint), window_funnel(3600 * 3, 'default', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test group by kbool order by kbool''' + qt_sql_window_funnel_BigInt_String_TimestampNs_Boolean_agg_phase_4 ''' + select count(distinct id), window_funnel(3600 * 3, 'default', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test''' + qt_sql_window_funnel_BigInt_String_TimestampNs_Boolean_gb_notnull ''' + select window_funnel(3600 * 3, 'default', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test_not_nullable group by kbool order by kbool''' + qt_sql_window_funnel_BigInt_String_TimestampNs_Boolean_notnull ''' + select window_funnel(3600 * 3, 'default', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test_not_nullable''' + qt_sql_window_funnel_BigInt_String_TimestampNs_Boolean_agg_phase_1_notnull ''' + select count(id), window_funnel(3600 * 3, 'default', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test_not_nullable group by id order by id''' + qt_sql_window_funnel_BigInt_String_TimestampNs_Boolean_agg_phase_2_notnull ''' + select count(distinct id), window_funnel(3600 * 3, 'default', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test_not_nullable''' + qt_sql_window_funnel_BigInt_String_TimestampNs_Boolean_agg_phase_3_notnull ''' + select count(distinct id, kint), window_funnel(3600 * 3, 'default', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test group by kbool order by kbool''' + qt_sql_window_funnel_BigInt_String_TimestampNs_Boolean_agg_phase_4_notnull ''' + select count(distinct id), window_funnel(3600 * 3, 'default', cast(kdtmv2s1 as timestamp_ns), kint = 1, kint = 2) from fn_test''' + } diff --git a/regression-test/suites/nereids_function_p0/gen_function/gen.groovy b/regression-test/suites/nereids_function_p0/gen_function/gen.groovy index 0d320a98bfda05..21947a1fa2dea9 100644 --- a/regression-test/suites/nereids_function_p0/gen_function/gen.groovy +++ b/regression-test/suites/nereids_function_p0/gen_function/gen.groovy @@ -94,7 +94,9 @@ suite("nereids_gen_fn") { order_qt_sql_explode_String_notnull "select id, e from fn_test_not_nullable lateral view explode(kastr) lv as e order by id, e" order_qt_sql_explode_DatetimeV2 "select id, e from fn_test lateral view explode(kadtmv2) lv as e order by id, e" + order_qt_sql_explode_TimestampNs "select id, e from fn_test lateral view explode(cast(kadtmv2 as array)) lv as e order by id, e" order_qt_sql_explode_DatetimeV2_notnull "select id, e from fn_test_not_nullable lateral view explode(kadtmv2) lv as e order by id, e" + order_qt_sql_explode_TimestampNs_notnull "select id, e from fn_test_not_nullable lateral view explode(cast(kadtmv2 as array)) lv as e order by id, e" order_qt_sql_explode_DateV2 "select id, e from fn_test lateral view explode(kadtv2) lv as e order by id, e" order_qt_sql_explode_DateV2_notnull "select id, e from fn_test_not_nullable lateral view explode(kadtv2) lv as e order by id, e" } diff --git a/regression-test/suites/nereids_function_p0/scalar_function/Array.groovy b/regression-test/suites/nereids_function_p0/scalar_function/Array.groovy index 9bdef14151b709..a96dce8cbec699 100644 --- a/regression-test/suites/nereids_function_p0/scalar_function/Array.groovy +++ b/regression-test/suites/nereids_function_p0/scalar_function/Array.groovy @@ -67,7 +67,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_compact_String_notnull "select array_compact(kastr) from fn_test_not_nullable" order_qt_sql_array_compact_DatetimeV2 "select array_compact(kadtmv2) from fn_test" + order_qt_sql_array_compact_TimestampNs "select array_compact(cast(kadtmv2 as array)) from fn_test" order_qt_sql_array_compact_DatetimeV2_notnull "select array_compact(kadtmv2) from fn_test_not_nullable" + order_qt_sql_array_compact_TimestampNs_notnull "select array_compact(cast(kadtmv2 as array)) from fn_test_not_nullable" order_qt_sql_array_compact_DateV2 "select array_compact(kadtv2) from fn_test" order_qt_sql_array_compact_DateV2_notnull "select array_compact(kadtv2) from fn_test_not_nullable" @@ -100,7 +102,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_concat_String_notnull "select array_concat(kastr, kastr) from fn_test_not_nullable" order_qt_sql_array_concat_DatetimeV2 "select array_concat(kadtmv2, kadtmv2) from fn_test" + order_qt_sql_array_concat_TimestampNs "select array_concat(cast(kadtmv2 as array), cast(kadtmv2 as array)) from fn_test" order_qt_sql_array_concat_DatetimeV2_notnull "select array_concat(kadtmv2, kadtmv2) from fn_test_not_nullable" + order_qt_sql_array_concat_TimestampNs_notnull "select array_concat(cast(kadtmv2 as array), cast(kadtmv2 as array)) from fn_test_not_nullable" order_qt_sql_array_concat_DateV2 "select array_concat(kadtv2, kadtv2) from fn_test" order_qt_sql_array_concat_DateV2_notnull "select array_concat(kadtv2, kadtv2) from fn_test_not_nullable" @@ -166,7 +170,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_distinct_String_notnull "select array_distinct(kastr) from fn_test_not_nullable" order_qt_sql_array_distinct_DatetimeV2 "select array_distinct(kadtmv2) from fn_test" + order_qt_sql_array_distinct_TimestampNs "select array_distinct(cast(kadtmv2 as array)) from fn_test" order_qt_sql_array_distinct_DatetimeV2_notnull "select array_distinct(kadtmv2) from fn_test_not_nullable" + order_qt_sql_array_distinct_TimestampNs_notnull "select array_distinct(cast(kadtmv2 as array)) from fn_test_not_nullable" order_qt_sql_array_distinct_DateV2 "select array_distinct(kadtv2) from fn_test" order_qt_sql_array_distinct_DateV2_notnull "select array_distinct(kadtv2) from fn_test_not_nullable" @@ -199,7 +205,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_except_String_notnull "select array_except(kastr, kastr) from fn_test_not_nullable" order_qt_sql_array_except_DatetimeV2 "select array_except(kadtmv2, kadtmv2) from fn_test" + order_qt_sql_array_except_TimestampNs "select array_except(cast(kadtmv2 as array), cast(kadtmv2 as array)) from fn_test" order_qt_sql_array_except_DatetimeV2_notnull "select array_except(kadtmv2, kadtmv2) from fn_test_not_nullable" + order_qt_sql_array_except_TimestampNs_notnull "select array_except(cast(kadtmv2 as array), cast(kadtmv2 as array)) from fn_test_not_nullable" order_qt_sql_array_except_DateV2 "select array_except(kadtv2, kadtv2) from fn_test" order_qt_sql_array_except_DateV2_notnull "select array_except(kadtv2, kadtv2) from fn_test_not_nullable" @@ -232,7 +240,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_intersect_String_notnull "select array_sort(array_intersect(kastr, kastr)) from fn_test_not_nullable" order_qt_sql_array_intersect_DatetimeV2 "select array_sort(array_intersect(kadtmv2, kadtmv2)) from fn_test" + order_qt_sql_array_intersect_TimestampNs "select array_sort(array_intersect(cast(kadtmv2 as array), cast(kadtmv2 as array))) from fn_test" order_qt_sql_array_intersect_DatetimeV2_notnull "select array_sort(array_intersect(kadtmv2, kadtmv2)) from fn_test_not_nullable" + order_qt_sql_array_intersect_TimestampNs_notnull "select array_sort(array_intersect(cast(kadtmv2 as array), cast(kadtmv2 as array))) from fn_test_not_nullable" order_qt_sql_array_intersect_DateV2 "select array_sort(array_intersect(kadtv2, kadtv2)) from fn_test" order_qt_sql_array_intersect_DateV2_notnull "select array_sort(array_intersect(kadtv2, kadtv2)) from fn_test_not_nullable" @@ -265,7 +275,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_join_String_notnull "select array_join(kastr, ',', 'null') from fn_test_not_nullable" order_qt_sql_array_join_DatetimeV2 "select array_join(kadtmv2, ',', 'null') from fn_test" + order_qt_sql_array_join_TimestampNs "select array_join(cast(kadtmv2 as array), ',', 'null') from fn_test" order_qt_sql_array_join_DatetimeV2_notnull "select array_join(kadtmv2, ',', 'null') from fn_test_not_nullable" + order_qt_sql_array_join_TimestampNs_notnull "select array_join(cast(kadtmv2 as array), ',', 'null') from fn_test_not_nullable" order_qt_sql_array_join_DateV2 "select array_join(kadtv2, ',', 'null') from fn_test" order_qt_sql_array_join_DateV2_notnull "select array_join(kadtv2, ',', 'null') from fn_test_not_nullable" @@ -297,7 +309,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_join_two_params_String_notnull "select array_join(kastr, ',') from fn_test_not_nullable" order_qt_sql_array_join_two_params_DatetimeV2 "select array_join(kadtmv2, ',') from fn_test" + order_qt_sql_array_join_two_params_TimestampNs "select array_join(cast(kadtmv2 as array), ',') from fn_test" order_qt_sql_array_join_two_params_DatetimeV2_notnull "select array_join(kadtmv2, ',') from fn_test_not_nullable" + order_qt_sql_array_join_two_params_TimestampNs_notnull "select array_join(cast(kadtmv2 as array), ',') from fn_test_not_nullable" order_qt_sql_array_join_two_params_DateV2 "select array_join(kadtv2, ',') from fn_test" order_qt_sql_array_join_two_params_DateV2_notnull "select array_join(kadtv2, ',') from fn_test_not_nullable" @@ -331,7 +345,9 @@ suite("nereids_scalar_fn_Array") { // order_qt_sql_array_max_String_notnull "select array_max(kastr) from fn_test_not_nullable" order_qt_sql_array_max_DatetimeV2 "select array_max(kadtmv2) from fn_test" + order_qt_sql_array_max_TimestampNs "select array_max(cast(kadtmv2 as array)) from fn_test" order_qt_sql_array_max_DatetimeV2_notnull "select array_max(kadtmv2) from fn_test_not_nullable" + order_qt_sql_array_max_TimestampNs_notnull "select array_max(cast(kadtmv2 as array)) from fn_test_not_nullable" order_qt_sql_array_max_DateV2 "select array_max(kadtv2) from fn_test" order_qt_sql_array_max_DateV2_notnull "select array_max(kadtv2) from fn_test_not_nullable" @@ -365,7 +381,9 @@ suite("nereids_scalar_fn_Array") { // order_qt_sql_array_min_String_notnull "select array_min(kastr) from fn_test_not_nullable" order_qt_sql_array_min_DatetimeV2 "select array_min(kadtmv2) from fn_test" + order_qt_sql_array_min_TimestampNs "select array_min(cast(kadtmv2 as array)) from fn_test" order_qt_sql_array_min_DatetimeV2_notnull "select array_min(kadtmv2) from fn_test_not_nullable" + order_qt_sql_array_min_TimestampNs_notnull "select array_min(cast(kadtmv2 as array)) from fn_test_not_nullable" order_qt_sql_array_min_DateV2 "select array_min(kadtv2) from fn_test" order_qt_sql_array_min_DateV2_notnull "select array_min(kadtv2) from fn_test_not_nullable" @@ -398,7 +416,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_popback_String_notnull "select array_popback(kastr) from fn_test_not_nullable" order_qt_sql_array_popback_DatetimeV2 "select array_popback(kadtmv2) from fn_test" + order_qt_sql_array_popback_TimestampNs "select array_popback(cast(kadtmv2 as array)) from fn_test" order_qt_sql_array_popback_DatetimeV2_notnull "select array_popback(kadtmv2) from fn_test_not_nullable" + order_qt_sql_array_popback_TimestampNs_notnull "select array_popback(cast(kadtmv2 as array)) from fn_test_not_nullable" order_qt_sql_array_popback_DateV2 "select array_popback(kadtv2) from fn_test" order_qt_sql_array_popback_DateV2_notnull "select array_popback(kadtv2) from fn_test_not_nullable" @@ -431,7 +451,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_popfront_String_notnull "select array_popfront(kastr) from fn_test_not_nullable" order_qt_sql_array_popfront_DatetimeV2 "select array_popfront(kadtmv2) from fn_test" + order_qt_sql_array_popfront_TimestampNs "select array_popfront(cast(kadtmv2 as array)) from fn_test" order_qt_sql_array_popfront_DatetimeV2_notnull "select array_popfront(kadtmv2) from fn_test_not_nullable" + order_qt_sql_array_popfront_TimestampNs_notnull "select array_popfront(cast(kadtmv2 as array)) from fn_test_not_nullable" order_qt_sql_array_popfront_DateV2 "select array_popfront(kadtv2) from fn_test" order_qt_sql_array_popfront_DateV2_notnull "select array_popfront(kadtv2) from fn_test_not_nullable" @@ -464,7 +486,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_position_String_notnull "select array_position(kastr, kstr) from fn_test_not_nullable" order_qt_sql_array_position_DatetimeV2 "select array_position(kadtmv2, kdtmv2s1) from fn_test" + order_qt_sql_array_position_TimestampNs "select array_position(cast(kadtmv2 as array), cast(kdtmv2s1 as timestamp_ns)) from fn_test" order_qt_sql_array_position_DatetimeV2_notnull "select array_position(kadtmv2, kdtmv2s1) from fn_test_not_nullable" + order_qt_sql_array_position_TimestampNs_notnull "select array_position(cast(kadtmv2 as array), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable" order_qt_sql_array_position_DateV2 "select array_position(kadtv2, kdtv2) from fn_test" order_qt_sql_array_position_DateV2_notnull "select array_position(kadtv2, kdtv2) from fn_test_not_nullable" @@ -515,7 +539,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_pushback_String_notnull "select array_pushback(kastr, kstr) from fn_test_not_nullable" order_qt_sql_array_pushback_DatetimeV2 "select array_pushback(kadtmv2, kdtmv2s1) from fn_test" + order_qt_sql_array_pushback_TimestampNs "select array_pushback(cast(kadtmv2 as array), cast(kdtmv2s1 as timestamp_ns)) from fn_test" order_qt_sql_array_pushback_DatetimeV2_notnull "select array_pushback(kadtmv2, kdtmv2s1) from fn_test_not_nullable" + order_qt_sql_array_pushback_TimestampNs_notnull "select array_pushback(cast(kadtmv2 as array), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable" order_qt_sql_array_pushback_DateV2 "select array_pushback(kadtv2, kdtv2) from fn_test" order_qt_sql_array_pushback_DateV2_notnull "select array_pushback(kadtv2, kdtv2) from fn_test_not_nullable" @@ -548,7 +574,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_pushfront_String_notnull "select array_pushfront(kastr, kstr) from fn_test_not_nullable" order_qt_sql_array_pushfront_DatetimeV2 "select array_pushfront(kadtmv2, kdtmv2s1) from fn_test" + order_qt_sql_array_pushfront_TimestampNs "select array_pushfront(cast(kadtmv2 as array), cast(kdtmv2s1 as timestamp_ns)) from fn_test" order_qt_sql_array_pushfront_DatetimeV2_notnull "select array_pushfront(kadtmv2, kdtmv2s1) from fn_test_not_nullable" + order_qt_sql_array_pushfront_TimestampNs_notnull "select array_pushfront(cast(kadtmv2 as array), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable" order_qt_sql_array_pushfront_DateV2 "select array_pushfront(kadtv2, kdtv2) from fn_test" order_qt_sql_array_pushfront_DateV2_notnull "select array_pushfront(kadtv2, kdtv2) from fn_test_not_nullable" @@ -594,7 +622,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_remove_String_notnull "select array_remove(kastr, kstr) from fn_test_not_nullable" order_qt_sql_array_remove_DatetimeV2 "select array_remove(kadtmv2, kdtmv2s1) from fn_test" + order_qt_sql_array_remove_TimestampNs "select array_remove(cast(kadtmv2 as array), cast(kdtmv2s1 as timestamp_ns)) from fn_test" order_qt_sql_array_remove_DatetimeV2_notnull "select array_remove(kadtmv2, kdtmv2s1) from fn_test_not_nullable" + order_qt_sql_array_remove_TimestampNs_notnull "select array_remove(cast(kadtmv2 as array), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable" order_qt_sql_array_remove_DateV2 "select array_remove(kadtv2, kdtv2) from fn_test" order_qt_sql_array_remove_DateV2_notnull "select array_remove(kadtv2, kdtv2) from fn_test_not_nullable" @@ -627,7 +657,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_reverse_sort_String_notnull "select array_reverse_sort(kastr) from fn_test_not_nullable" order_qt_sql_array_reverse_sort_DatetimeV2 "select array_reverse_sort(kadtmv2) from fn_test" + order_qt_sql_array_reverse_sort_TimestampNs "select array_reverse_sort(cast(kadtmv2 as array)) from fn_test" order_qt_sql_array_reverse_sort_DatetimeV2_notnull "select array_reverse_sort(kadtmv2) from fn_test_not_nullable" + order_qt_sql_array_reverse_sort_TimestampNs_notnull "select array_reverse_sort(cast(kadtmv2 as array)) from fn_test_not_nullable" order_qt_sql_array_reverse_sort_DateV2 "select array_reverse_sort(kadtv2) from fn_test" order_qt_sql_array_reverse_sort_DateV2_notnull "select array_reverse_sort(kadtv2) from fn_test_not_nullable" @@ -660,7 +692,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_slice_String_notnull "select array_slice(kastr, kint) from fn_test_not_nullable" order_qt_sql_array_slice_DatetimeV2 "select array_slice(kadtmv2, kint) from fn_test" + order_qt_sql_array_slice_TimestampNs "select array_slice(cast(kadtmv2 as array), kint) from fn_test" order_qt_sql_array_slice_DatetimeV2_notnull "select array_slice(kadtmv2, kint) from fn_test_not_nullable" + order_qt_sql_array_slice_TimestampNs_notnull "select array_slice(cast(kadtmv2 as array), kint) from fn_test_not_nullable" order_qt_sql_array_slice_DateV2 "select array_slice(kadtv2, kint) from fn_test" order_qt_sql_array_slice_DateV2_notnull "select array_slice(kadtv2, kint) from fn_test_not_nullable" @@ -693,7 +727,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_slice_three_params_String_notnull "select array_slice(kastr, kint, ktint) from fn_test_not_nullable" order_qt_sql_array_slice_three_params_DatetimeV2 "select array_slice(kadtmv2, kint, ktint) from fn_test" + order_qt_sql_array_slice_three_params_TimestampNs "select array_slice(cast(kadtmv2 as array), kint, ktint) from fn_test" order_qt_sql_array_slice_three_params_DatetimeV2_notnull "select array_slice(kadtmv2, kint, ktint) from fn_test_not_nullable" + order_qt_sql_array_slice_three_params_TimestampNs_notnull "select array_slice(cast(kadtmv2 as array), kint, ktint) from fn_test_not_nullable" order_qt_sql_array_slice_three_params_DateV2 "select array_slice(kadtv2, kint, ktint) from fn_test" order_qt_sql_array_slice_three_params_DateV2_notnull "select array_slice(kadtv2, kint, ktint) from fn_test_not_nullable" @@ -726,7 +762,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_sort_String_notnull "select array_sort(kastr) from fn_test_not_nullable" order_qt_sql_array_sort_DatetimeV2 "select array_sort(kadtmv2) from fn_test" + order_qt_sql_array_sort_TimestampNs "select array_sort(cast(kadtmv2 as array)) from fn_test" order_qt_sql_array_sort_DatetimeV2_notnull "select array_sort(kadtmv2) from fn_test_not_nullable" + order_qt_sql_array_sort_TimestampNs_notnull "select array_sort(cast(kadtmv2 as array)) from fn_test_not_nullable" order_qt_sql_array_sort_DateV2 "select array_sort(kadtv2) from fn_test" order_qt_sql_array_sort_DateV2_notnull "select array_sort(kadtv2) from fn_test_not_nullable" @@ -777,7 +815,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_union_String_notnull "select array_sort(array_union(kastr, kastr)) from fn_test_not_nullable" order_qt_sql_array_union_DatetimeV2 "select array_sort(array_union(kadtmv2, kadtmv2)) from fn_test" + order_qt_sql_array_union_TimestampNs "select array_sort(array_union(cast(kadtmv2 as array), cast(kadtmv2 as array))) from fn_test" order_qt_sql_array_union_DatetimeV2_notnull "select array_sort(array_union(kadtmv2, kadtmv2)) from fn_test_not_nullable" + order_qt_sql_array_union_TimestampNs_notnull "select array_sort(array_union(cast(kadtmv2 as array), cast(kadtmv2 as array))) from fn_test_not_nullable" order_qt_sql_array_union_DateV2 "select array_sort(array_union(kadtv2, kadtv2)) from fn_test" order_qt_sql_array_union_DateV2_notnull "select array_sort(array_union(kadtv2, kadtv2)) from fn_test_not_nullable" @@ -810,7 +850,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_with_constant_String_notnull "select array_with_constant(kint, kstr) from fn_test_not_nullable" order_qt_sql_array_with_constant_DatetimeV2 "select array_with_constant(kint, kdtmv2s1) from fn_test" + order_qt_sql_array_with_constant_TimestampNs "select array_with_constant(kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test" order_qt_sql_array_with_constant_DatetimeV2_notnull "select array_with_constant(kint, kdtmv2s1) from fn_test_not_nullable" + order_qt_sql_array_with_constant_TimestampNs_notnull "select array_with_constant(kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable" order_qt_sql_array_with_constant_DateV2 "select array_with_constant(kint, kdtv2) from fn_test" order_qt_sql_array_with_constant_DateV2_notnull "select array_with_constant(kint, kdtv2) from fn_test_not_nullable" @@ -843,7 +885,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_cardinality_String_notnull "select cardinality(kastr) from fn_test_not_nullable" order_qt_sql_cardinality_DatetimeV2 "select cardinality(kadtmv2) from fn_test" + order_qt_sql_cardinality_TimestampNs "select cardinality(cast(kadtmv2 as array)) from fn_test" order_qt_sql_cardinality_DatetimeV2_notnull "select cardinality(kadtmv2) from fn_test_not_nullable" + order_qt_sql_cardinality_TimestampNs_notnull "select cardinality(cast(kadtmv2 as array)) from fn_test_not_nullable" order_qt_sql_cardinality_DateV2 "select cardinality(kadtv2) from fn_test" order_qt_sql_cardinality_DateV2_notnull "select cardinality(kadtv2) from fn_test_not_nullable" @@ -876,7 +920,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_size_String_notnull "select array_size(kastr) from fn_test_not_nullable" order_qt_sql_array_size_DatetimeV2 "select array_size(kadtmv2) from fn_test" + order_qt_sql_array_size_TimestampNs "select array_size(cast(kadtmv2 as array)) from fn_test" order_qt_sql_array_size_DatetimeV2_notnull "select array_size(kadtmv2) from fn_test_not_nullable" + order_qt_sql_array_size_TimestampNs_notnull "select array_size(cast(kadtmv2 as array)) from fn_test_not_nullable" order_qt_sql_array_size_DateV2 "select array_size(kadtv2) from fn_test" order_qt_sql_array_size_DateV2_notnull "select array_size(kadtv2) from fn_test_not_nullable" @@ -909,7 +955,9 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_size_String_notnull "select size(kastr) from fn_test_not_nullable" order_qt_sql_size_DatetimeV2 "select size(kadtmv2) from fn_test" + order_qt_sql_size_TimestampNs "select size(cast(kadtmv2 as array)) from fn_test" order_qt_sql_size_DatetimeV2_notnull "select size(kadtmv2) from fn_test_not_nullable" + order_qt_sql_size_TimestampNs_notnull "select size(cast(kadtmv2 as array)) from fn_test_not_nullable" order_qt_sql_size_DateV2 "select size(kadtv2) from fn_test" order_qt_sql_size_DateV2_notnull "select size(kadtv2) from fn_test_not_nullable" @@ -1190,6 +1238,9 @@ suite("nereids_scalar_fn_Array") { qt_array_apply1 """select array_apply(c_array_datetimev2, "=", '2022-12-02 22:23:24.999999') from test_array_with_scale_type_table""" qt_array_apply2 """select array_apply(c_array_datetimev2, ">", '2022-12-01 22:23:24.999999') from test_array_with_scale_type_table""" qt_array_apply3 """select array_apply(c_array_datetimev2, ">", null) from test_array_with_scale_type_table""" + order_qt_array_apply_timestamp_ns_eq """select array_apply(cast(c_array_datetimev2 as array), "=", cast('2022-12-02 22:23:24.999999' as timestamp_ns)) from test_array_with_scale_type_table""" + order_qt_array_apply_timestamp_ns_gt """select array_apply(cast(c_array_datetimev2 as array), ">", cast('2022-12-01 22:23:24.999999' as timestamp_ns)) from test_array_with_scale_type_table""" + order_qt_array_apply_timestamp_ns_null """select array_apply(cast(c_array_datetimev2 as array), ">", null) from test_array_with_scale_type_table""" qt_array_apply4 """select array_apply(c_array_decimal, "=", 22.679) from test_array_with_scale_type_table""" qt_array_apply5 """select array_apply(c_array_decimal, ">=", 22.1) from test_array_with_scale_type_table""" qt_array_apply6 """select array_apply(c_array_decimal, ">=", null) from test_array_with_scale_type_table""" @@ -1205,24 +1256,36 @@ suite("nereids_scalar_fn_Array") { // array_range with datetime argument, sequence with int and datetime argument qt_array_range_datetime1 """select array_range(kdtmv2s1, date_add(kdtmv2s1, interval kint+1 day), interval kint day) from fn_test order by kdtmv2s1;""" + qt_array_range_datetime1_timestamp_ns """select array_range(cast(kdtmv2s1 as timestamp_ns), date_add(cast(kdtmv2s1 as timestamp_ns), interval kint+1 day), interval kint day) from fn_test order by cast(kdtmv2s1 as timestamp_ns);""" qt_array_range_datetime2 """select array_range(kdtmv2s1, date_add(kdtmv2s1, interval kint+2 week), interval kint week) from fn_test order by kdtmv2s1;""" + qt_array_range_datetime2_timestamp_ns """select array_range(cast(kdtmv2s1 as timestamp_ns), date_add(cast(kdtmv2s1 as timestamp_ns), interval kint+2 week), interval kint week) from fn_test order by cast(kdtmv2s1 as timestamp_ns);""" qt_array_range_datetime3 """select array_range(kdtmv2s1, date_add(kdtmv2s1, interval kint+2 quarter), interval kint quarter) from fn_test order by kdtmv2s1;""" + qt_array_range_datetime3_timestamp_ns """select array_range(cast(kdtmv2s1 as timestamp_ns), date_add(cast(kdtmv2s1 as timestamp_ns), interval kint+2 quarter), interval kint quarter) from fn_test order by cast(kdtmv2s1 as timestamp_ns);""" qt_sequence_int_one_para """select sequence(kint) from fn_test order by kint;""" qt_sequence_int_two_para """select sequence(kint, kint+2) from fn_test order by kint;""" qt_sequence_int_three_para """select sequence(kint-1, kint+2, 1) from fn_test order by kint;""" qt_sequence_datetime_default """select sequence(kdtmv2s1, date_add(kdtmv2s1, interval kint-3 day)) from fn_test order by kdtmv2s1;""" + qt_sequence_datetime_default_timestamp_ns """select sequence(cast(kdtmv2s1 as timestamp_ns), date_add(cast(kdtmv2s1 as timestamp_ns), interval kint-3 day)) from fn_test order by cast(kdtmv2s1 as timestamp_ns);""" qt_sequence_datetime_day """select sequence(kdtmv2s1, date_add(kdtmv2s1, interval kint+1 day), interval kint day) from fn_test order by kdtmv2s1;""" + qt_sequence_datetime_day_timestamp_ns """select sequence(cast(kdtmv2s1 as timestamp_ns), date_add(cast(kdtmv2s1 as timestamp_ns), interval kint+1 day), interval kint day) from fn_test order by cast(kdtmv2s1 as timestamp_ns);""" qt_sequence_datetime_week """select sequence(kdtmv2s1, date_add(kdtmv2s1, interval kint+2 week), interval kint week) from fn_test order by kdtmv2s1;""" + qt_sequence_datetime_week_timestamp_ns """select sequence(cast(kdtmv2s1 as timestamp_ns), date_add(cast(kdtmv2s1 as timestamp_ns), interval kint+2 week), interval kint week) from fn_test order by cast(kdtmv2s1 as timestamp_ns);""" qt_sequence_datetime_month """select sequence(kdtmv2s1, date_add(kdtmv2s1, interval kint+3 month), interval kint month) from fn_test order by kdtmv2s1;""" + qt_sequence_datetime_month_timestamp_ns """select sequence(cast(kdtmv2s1 as timestamp_ns), date_add(cast(kdtmv2s1 as timestamp_ns), interval kint+3 month), interval kint month) from fn_test order by cast(kdtmv2s1 as timestamp_ns);""" qt_sequence_datetime_year """select sequence(kdtmv2s1, date_add(kdtmv2s1, interval kint+3 year), interval kint year) from fn_test order by kdtmv2s1;""" + qt_sequence_datetime_year_timestamp_ns """select sequence(cast(kdtmv2s1 as timestamp_ns), date_add(cast(kdtmv2s1 as timestamp_ns), interval kint+3 year), interval kint year) from fn_test order by cast(kdtmv2s1 as timestamp_ns);""" qt_sequence_datetime_hour """select sequence(kdtmv2s1, date_add(kdtmv2s1, interval kint-3 hour), interval kint hour) from fn_test order by kdtmv2s1;""" + qt_sequence_datetime_hour_timestamp_ns """select sequence(cast(kdtmv2s1 as timestamp_ns), date_add(cast(kdtmv2s1 as timestamp_ns), interval kint-3 hour), interval kint hour) from fn_test order by cast(kdtmv2s1 as timestamp_ns);""" qt_sequence_datetime_minute """select sequence(kdtmv2s1, date_add(kdtmv2s1, interval kint+1 minute), interval kint minute) from fn_test order by kdtmv2s1;""" + qt_sequence_datetime_minute_timestamp_ns """select sequence(cast(kdtmv2s1 as timestamp_ns), date_add(cast(kdtmv2s1 as timestamp_ns), interval kint+1 minute), interval kint minute) from fn_test order by cast(kdtmv2s1 as timestamp_ns);""" qt_sequence_datetime_second """select sequence(kdtmv2s1, date_add(kdtmv2s1, interval kint second), interval kint-1 second) from fn_test order by kdtmv2s1;""" + qt_sequence_datetime_second_timestamp_ns """select sequence(cast(kdtmv2s1 as timestamp_ns), date_add(cast(kdtmv2s1 as timestamp_ns), interval kint second), interval kint-1 second) from fn_test order by cast(kdtmv2s1 as timestamp_ns);""" // max_array_size_as_field = 1000000; sql "select count(sequence(kdtmv2s1, date_add(kdtmv2s1, interval kint+1000 year))) from fn_test" sql "select count(sequence(kdtmv2s1, date_add(kdtmv2s1, interval kint+1000 year), INTERVAL 5 YEAR)) from fn_test" order_qt_sql_sequence_dt_3args "select sequence(kdtmv2s1, date_add(kdtmv2s1, interval kint+1000 year), INTERVAL 125 YEAR) from fn_test" + order_qt_sql_sequence_dt_3args_timestamp_ns "select sequence(cast(kdtmv2s1 as timestamp_ns), date_add(cast(kdtmv2s1 as timestamp_ns), interval kint+100 year), INTERVAL 12 YEAR) from fn_test" sql "select count(sequence(kint, kint+100000)) from fn_test" sql "select count(sequence(kint, kint+100000, 10000)) from fn_test" order_qt_sql_sequence_int_3args "select sequence(kint, kint+100000, 10000) from fn_test" diff --git a/regression-test/suites/nereids_function_p0/scalar_function/Array1.groovy b/regression-test/suites/nereids_function_p0/scalar_function/Array1.groovy index b7e81adc8e26a9..5b99791e34fa2a 100644 --- a/regression-test/suites/nereids_function_p0/scalar_function/Array1.groovy +++ b/regression-test/suites/nereids_function_p0/scalar_function/Array1.groovy @@ -74,7 +74,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_array_compact_String_notnull "select array_compact(kastr) from $not_nullable_tb order by id" order_qt_sql_array_compact_DatetimeV2 "select array_compact(kadtmv2) from $nullable_tb order by id" + order_qt_sql_array_compact_TimestampNs "select array_compact(cast(kadtmv2 as array)) from $nullable_tb order by id" order_qt_sql_array_compact_DatetimeV2_notnull "select array_compact(kadtmv2) from $not_nullable_tb order by id" + order_qt_sql_array_compact_TimestampNs_notnull "select array_compact(cast(kadtmv2 as array)) from $not_nullable_tb order by id" order_qt_sql_array_compact_DateV2 "select array_compact(kadtv2) from $nullable_tb order by id" order_qt_sql_array_compact_DateV2_notnull "select array_compact(kadtv2) from $not_nullable_tb order by id" @@ -107,7 +109,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_array_concat_String_notnull "select array_concat(kastr, kastr) from $not_nullable_tb order by id" order_qt_sql_array_concat_DatetimeV2 "select array_concat(kadtmv2, kadtmv2) from $nullable_tb order by id" + order_qt_sql_array_concat_TimestampNs "select array_concat(cast(kadtmv2 as array), cast(kadtmv2 as array)) from $nullable_tb order by id" order_qt_sql_array_concat_DatetimeV2_notnull "select array_concat(kadtmv2, kadtmv2) from $not_nullable_tb order by id" + order_qt_sql_array_concat_TimestampNs_notnull "select array_concat(cast(kadtmv2 as array), cast(kadtmv2 as array)) from $not_nullable_tb order by id" order_qt_sql_array_concat_DateV2 "select array_concat(kadtv2, kadtv2) from $nullable_tb order by id" order_qt_sql_array_concat_DateV2_notnull "select array_concat(kadtv2, kadtv2) from $not_nullable_tb order by id" @@ -173,7 +177,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_array_distinct_String_notnull "select array_distinct(kastr) from $not_nullable_tb order by id" order_qt_sql_array_distinct_DatetimeV2 "select array_distinct(kadtmv2) from $nullable_tb order by id" + order_qt_sql_array_distinct_TimestampNs "select array_distinct(cast(kadtmv2 as array)) from $nullable_tb order by id" order_qt_sql_array_distinct_DatetimeV2_notnull "select array_distinct(kadtmv2) from $not_nullable_tb order by id" + order_qt_sql_array_distinct_TimestampNs_notnull "select array_distinct(cast(kadtmv2 as array)) from $not_nullable_tb order by id" order_qt_sql_array_distinct_DateV2 "select array_distinct(kadtv2) from $nullable_tb order by id" order_qt_sql_array_distinct_DateV2_notnull "select array_distinct(kadtv2) from $not_nullable_tb order by id" @@ -211,7 +217,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_array_except_String_notnull "select array_except(kastr, kastr) from $not_nullable_tb order by id" order_qt_sql_array_except_DatetimeV2 "select array_except(kadtmv2, kadtmv2) from $nullable_tb order by id" + order_qt_sql_array_except_TimestampNs "select array_except(cast(kadtmv2 as array), cast(kadtmv2 as array)) from $nullable_tb order by id" order_qt_sql_array_except_DatetimeV2_notnull "select array_except(kadtmv2, kadtmv2) from $not_nullable_tb order by id" + order_qt_sql_array_except_TimestampNs_notnull "select array_except(cast(kadtmv2 as array), cast(kadtmv2 as array)) from $not_nullable_tb order by id" order_qt_sql_array_except_DateV2 "select array_except(kadtv2, kadtv2) from $nullable_tb order by id" order_qt_sql_array_except_DateV2_notnull "select array_except(kadtv2, kadtv2) from $not_nullable_tb order by id" @@ -244,7 +252,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_array_intersect_String_notnull "select array_sort(array_intersect(kastr, kastr)) from $not_nullable_tb order by id" order_qt_sql_array_intersect_DatetimeV2 "select array_sort(array_intersect(kadtmv2, kadtmv2)) from $nullable_tb order by id" + order_qt_sql_array_intersect_TimestampNs "select array_sort(array_intersect(cast(kadtmv2 as array), cast(kadtmv2 as array))) from $nullable_tb order by id" order_qt_sql_array_intersect_DatetimeV2_notnull "select array_sort(array_intersect(kadtmv2, kadtmv2)) from $not_nullable_tb order by id" + order_qt_sql_array_intersect_TimestampNs_notnull "select array_sort(array_intersect(cast(kadtmv2 as array), cast(kadtmv2 as array))) from $not_nullable_tb order by id" order_qt_sql_array_intersect_DateV2 "select array_sort(array_intersect(kadtv2, kadtv2)) from $nullable_tb order by id" order_qt_sql_array_intersect_DateV2_notnull "select array_sort(array_intersect(kadtv2, kadtv2)) from $not_nullable_tb order by id" @@ -277,7 +287,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_array_join_String_notnull "select array_join(kastr, ',', 'null') from $not_nullable_tb order by id" order_qt_sql_array_join_DatetimeV2 "select array_join(kadtmv2, ',', 'null') from $nullable_tb order by id" + order_qt_sql_array_join_TimestampNs "select array_join(cast(kadtmv2 as array), ',', 'null') from $nullable_tb order by id" order_qt_sql_array_join_DatetimeV2_notnull "select array_join(kadtmv2, ',', 'null') from $not_nullable_tb order by id" + order_qt_sql_array_join_TimestampNs_notnull "select array_join(cast(kadtmv2 as array), ',', 'null') from $not_nullable_tb order by id" order_qt_sql_array_join_DateV2 "select array_join(kadtv2, ',', 'null') from $nullable_tb order by id" order_qt_sql_array_join_DateV2_notnull "select array_join(kadtv2, ',', 'null') from $not_nullable_tb order by id" @@ -309,7 +321,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_array_join_two_params_String_notnull "select array_join(kastr, ',') from $not_nullable_tb order by id" order_qt_sql_array_join_two_params_DatetimeV2 "select array_join(kadtmv2, ',') from $nullable_tb order by id" + order_qt_sql_array_join_two_params_TimestampNs "select array_join(cast(kadtmv2 as array), ',') from $nullable_tb order by id" order_qt_sql_array_join_two_params_DatetimeV2_notnull "select array_join(kadtmv2, ',') from $not_nullable_tb order by id" + order_qt_sql_array_join_two_params_TimestampNs_notnull "select array_join(cast(kadtmv2 as array), ',') from $not_nullable_tb order by id" order_qt_sql_array_join_two_params_DateV2 "select array_join(kadtv2, ',') from $nullable_tb order by id" order_qt_sql_array_join_two_params_DateV2_notnull "select array_join(kadtv2, ',') from $not_nullable_tb order by id" @@ -343,7 +357,9 @@ suite("nereids_scalar_fn_Array1") { // order_qt_sql_array_max_String_notnull "select array_max(kastr) from $not_nullable_tb order by id" order_qt_sql_array_max_DatetimeV2 "select array_max(kadtmv2) from $nullable_tb order by id" + order_qt_sql_array_max_TimestampNs "select array_max(cast(kadtmv2 as array)) from $nullable_tb order by id" order_qt_sql_array_max_DatetimeV2_notnull "select array_max(kadtmv2) from $not_nullable_tb order by id" + order_qt_sql_array_max_TimestampNs_notnull "select array_max(cast(kadtmv2 as array)) from $not_nullable_tb order by id" order_qt_sql_array_max_DateV2 "select array_max(kadtv2) from $nullable_tb order by id" order_qt_sql_array_max_DateV2_notnull "select array_max(kadtv2) from $not_nullable_tb order by id" @@ -377,7 +393,9 @@ suite("nereids_scalar_fn_Array1") { // order_qt_sql_array_min_String_notnull "select array_min(kastr) from $not_nullable_tb order by id" order_qt_sql_array_min_DatetimeV2 "select array_min(kadtmv2) from $nullable_tb order by id" + order_qt_sql_array_min_TimestampNs "select array_min(cast(kadtmv2 as array)) from $nullable_tb order by id" order_qt_sql_array_min_DatetimeV2_notnull "select array_min(kadtmv2) from $not_nullable_tb order by id" + order_qt_sql_array_min_TimestampNs_notnull "select array_min(cast(kadtmv2 as array)) from $not_nullable_tb order by id" order_qt_sql_array_min_DateV2 "select array_min(kadtv2) from $nullable_tb order by id" order_qt_sql_array_min_DateV2_notnull "select array_min(kadtv2) from $not_nullable_tb order by id" @@ -410,7 +428,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_array_popback_String_notnull "select array_popback(kastr) from $not_nullable_tb order by id" order_qt_sql_array_popback_DatetimeV2 "select array_popback(kadtmv2) from $nullable_tb order by id" + order_qt_sql_array_popback_TimestampNs "select array_popback(cast(kadtmv2 as array)) from $nullable_tb order by id" order_qt_sql_array_popback_DatetimeV2_notnull "select array_popback(kadtmv2) from $not_nullable_tb order by id" + order_qt_sql_array_popback_TimestampNs_notnull "select array_popback(cast(kadtmv2 as array)) from $not_nullable_tb order by id" order_qt_sql_array_popback_DateV2 "select array_popback(kadtv2) from $nullable_tb order by id" order_qt_sql_array_popback_DateV2_notnull "select array_popback(kadtv2) from $not_nullable_tb order by id" @@ -443,7 +463,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_array_popfront_String_notnull "select array_popfront(kastr) from $not_nullable_tb order by id" order_qt_sql_array_popfront_DatetimeV2 "select array_popfront(kadtmv2) from $nullable_tb order by id" + order_qt_sql_array_popfront_TimestampNs "select array_popfront(cast(kadtmv2 as array)) from $nullable_tb order by id" order_qt_sql_array_popfront_DatetimeV2_notnull "select array_popfront(kadtmv2) from $not_nullable_tb order by id" + order_qt_sql_array_popfront_TimestampNs_notnull "select array_popfront(cast(kadtmv2 as array)) from $not_nullable_tb order by id" order_qt_sql_array_popfront_DateV2 "select array_popfront(kadtv2) from $nullable_tb order by id" order_qt_sql_array_popfront_DateV2_notnull "select array_popfront(kadtv2) from $not_nullable_tb order by id" @@ -474,7 +496,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_array_position_Varchar_notnull "select array_position(kavchr, element_at(kavchr, 1)) from $not_nullable_tb order by id" order_qt_sql_array_position_DatetimeV2 "select array_position(kadtmv2, element_at(kadtmv2, 1)) from $nullable_tb order by id" + order_qt_sql_array_position_TimestampNs "select array_position(cast(kadtmv2 as array), element_at(cast(kadtmv2 as array), 1)) from $nullable_tb order by id" order_qt_sql_array_position_DatetimeV2_notnull "select array_position(kadtmv2, element_at(kadtmv2, 1)) from $not_nullable_tb order by id" + order_qt_sql_array_position_TimestampNs_notnull "select array_position(cast(kadtmv2 as array), element_at(cast(kadtmv2 as array), 1)) from $not_nullable_tb order by id" order_qt_sql_array_position_DateV2 "select array_position(kadtv2, element_at(kadtv2, 1)) from $nullable_tb order by id" order_qt_sql_array_position_DateV2_notnull "select array_position(kadtv2, element_at(kadtv2, 1)) from $not_nullable_tb order by id" @@ -519,7 +543,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_array_pushback_String_notnull "select array_pushback(kastr, element_at(kastr, 1)) from $not_nullable_tb order by id" order_qt_sql_array_pushback_DatetimeV2 "select array_pushback(kadtmv2, element_at(kadtmv2, 1)) from $nullable_tb order by id" + order_qt_sql_array_pushback_TimestampNs "select array_pushback(cast(kadtmv2 as array), element_at(cast(kadtmv2 as array), 1)) from $nullable_tb order by id" order_qt_sql_array_pushback_DatetimeV2_notnull "select array_pushback(kadtmv2, element_at(kadtmv2, 1)) from $not_nullable_tb order by id" + order_qt_sql_array_pushback_TimestampNs_notnull "select array_pushback(cast(kadtmv2 as array), element_at(cast(kadtmv2 as array), 1)) from $not_nullable_tb order by id" order_qt_sql_array_pushback_DateV2 "select array_pushback(kadtv2, element_at(kadtv2, 1)) from $nullable_tb order by id" order_qt_sql_array_pushback_DateV2_notnull "select array_pushback(kadtv2, element_at(kadtv2, 1)) from $not_nullable_tb order by id" @@ -552,7 +578,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_array_pushfront_String_notnull "select array_pushfront(kastr, element_at(kastr, 1)) from $not_nullable_tb order by id" order_qt_sql_array_pushfront_DatetimeV2 "select array_pushfront(kadtmv2, element_at(kadtmv2, 1)) from $nullable_tb order by id" + order_qt_sql_array_pushfront_TimestampNs "select array_pushfront(cast(kadtmv2 as array), element_at(cast(kadtmv2 as array), 1)) from $nullable_tb order by id" order_qt_sql_array_pushfront_DatetimeV2_notnull "select array_pushfront(kadtmv2, element_at(kadtmv2, 1)) from $not_nullable_tb order by id" + order_qt_sql_array_pushfront_TimestampNs_notnull "select array_pushfront(cast(kadtmv2 as array), element_at(cast(kadtmv2 as array), 1)) from $not_nullable_tb order by id" order_qt_sql_array_pushfront_DateV2 "select array_pushfront(kadtv2, element_at(kadtv2, 1)) from $nullable_tb order by id" order_qt_sql_array_pushfront_DateV2_notnull "select array_pushfront(kadtv2, element_at(kadtv2, 1)) from $not_nullable_tb order by id" @@ -599,7 +627,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_array_remove_String_notnull "select array_remove(kastr, element_at(kastr, 1)) from $not_nullable_tb order by id" order_qt_sql_array_remove_DatetimeV2 "select array_remove(kadtmv2, element_at(kadtmv2, 1)) from $nullable_tb order by id" + order_qt_sql_array_remove_TimestampNs "select array_remove(cast(kadtmv2 as array), element_at(cast(kadtmv2 as array), 1)) from $nullable_tb order by id" order_qt_sql_array_remove_DatetimeV2_notnull "select array_remove(kadtmv2, element_at(kadtmv2, 1)) from $not_nullable_tb order by id" + order_qt_sql_array_remove_TimestampNs_notnull "select array_remove(cast(kadtmv2 as array), element_at(cast(kadtmv2 as array), 1)) from $not_nullable_tb order by id" order_qt_sql_array_remove_DateV2 "select array_remove(kadtv2, element_at(kadtv2, 1)) from $nullable_tb order by id" order_qt_sql_array_remove_DateV2_notnull "select array_remove(kadtv2, element_at(kadtv2, 1)) from $not_nullable_tb order by id" @@ -632,7 +662,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_array_reverse_sort_String_notnull "select array_reverse_sort(kastr) from $not_nullable_tb order by id" order_qt_sql_array_reverse_sort_DatetimeV2 "select array_reverse_sort(kadtmv2) from $nullable_tb order by id" + order_qt_sql_array_reverse_sort_TimestampNs "select array_reverse_sort(cast(kadtmv2 as array)) from $nullable_tb order by id" order_qt_sql_array_reverse_sort_DatetimeV2_notnull "select array_reverse_sort(kadtmv2) from $not_nullable_tb order by id" + order_qt_sql_array_reverse_sort_TimestampNs_notnull "select array_reverse_sort(cast(kadtmv2 as array)) from $not_nullable_tb order by id" order_qt_sql_array_reverse_sort_DateV2 "select array_reverse_sort(kadtv2) from $nullable_tb order by id" order_qt_sql_array_reverse_sort_DateV2_notnull "select array_reverse_sort(kadtv2) from $not_nullable_tb order by id" @@ -665,7 +697,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_array_slice_String_notnull "select array_slice(kastr, element_at(kaint, 1)) from $not_nullable_tb order by id" order_qt_sql_array_slice_DatetimeV2 "select array_slice(kadtmv2, element_at(kaint, 1)) from $nullable_tb order by id" + order_qt_sql_array_slice_TimestampNs "select array_slice(cast(kadtmv2 as array), element_at(kaint, 1)) from $nullable_tb order by id" order_qt_sql_array_slice_DatetimeV2_notnull "select array_slice(kadtmv2, element_at(kaint, 1)) from $not_nullable_tb order by id" + order_qt_sql_array_slice_TimestampNs_notnull "select array_slice(cast(kadtmv2 as array), element_at(kaint, 1)) from $not_nullable_tb order by id" order_qt_sql_array_slice_DateV2 "select array_slice(kadtv2, element_at(kaint, 1)) from $nullable_tb order by id" order_qt_sql_array_slice_DateV2_notnull "select array_slice(kadtv2, element_at(kaint, 1)) from $not_nullable_tb order by id" @@ -698,7 +732,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_array_slice_three_params_String_notnull "select array_slice(kastr, element_at(kaint, 1), element_at(katint, 1)) from $not_nullable_tb order by id" order_qt_sql_array_slice_three_params_DatetimeV2 "select array_slice(kadtmv2, element_at(kaint, 1), element_at(katint, 1)) from $nullable_tb order by id" + order_qt_sql_array_slice_three_params_TimestampNs "select array_slice(cast(kadtmv2 as array), element_at(kaint, 1), element_at(katint, 1)) from $nullable_tb order by id" order_qt_sql_array_slice_three_params_DatetimeV2_notnull "select array_slice(kadtmv2, element_at(kaint, 1), element_at(katint, 1)) from $not_nullable_tb order by id" + order_qt_sql_array_slice_three_params_TimestampNs_notnull "select array_slice(cast(kadtmv2 as array), element_at(kaint, 1), element_at(katint, 1)) from $not_nullable_tb order by id" order_qt_sql_array_slice_three_params_DateV2 "select array_slice(kadtv2, element_at(kaint, 1), element_at(katint, 1)) from $nullable_tb order by id" order_qt_sql_array_slice_three_params_DateV2_notnull "select array_slice(kadtv2, element_at(kaint, 1), element_at(katint, 1)) from $not_nullable_tb order by id" @@ -731,7 +767,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_array_sort_String_notnull "select array_sort(kastr) from $not_nullable_tb order by id" order_qt_sql_array_sort_DatetimeV2 "select array_sort(kadtmv2) from $nullable_tb order by id" + order_qt_sql_array_sort_TimestampNs "select array_sort(cast(kadtmv2 as array)) from $nullable_tb order by id" order_qt_sql_array_sort_DatetimeV2_notnull "select array_sort(kadtmv2) from $not_nullable_tb order by id" + order_qt_sql_array_sort_TimestampNs_notnull "select array_sort(cast(kadtmv2 as array)) from $not_nullable_tb order by id" order_qt_sql_array_sort_DateV2 "select array_sort(kadtv2) from $nullable_tb order by id" order_qt_sql_array_sort_DateV2_notnull "select array_sort(kadtv2) from $not_nullable_tb order by id" @@ -782,7 +820,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_array_union_String_notnull "select array_sort(array_union(kastr, kastr)) from $not_nullable_tb order by id" order_qt_sql_array_union_DatetimeV2 "select array_sort(array_union(kadtmv2, kadtmv2)) from $nullable_tb order by id" + order_qt_sql_array_union_TimestampNs "select array_sort(array_union(cast(kadtmv2 as array), cast(kadtmv2 as array))) from $nullable_tb order by id" order_qt_sql_array_union_DatetimeV2_notnull "select array_sort(array_union(kadtmv2, kadtmv2)) from $not_nullable_tb order by id" + order_qt_sql_array_union_TimestampNs_notnull "select array_sort(array_union(cast(kadtmv2 as array), cast(kadtmv2 as array))) from $not_nullable_tb order by id" order_qt_sql_array_union_DateV2 "select array_sort(array_union(kadtv2, kadtv2)) from $nullable_tb order by id" order_qt_sql_array_union_DateV2_notnull "select array_sort(array_union(kadtv2, kadtv2)) from $not_nullable_tb order by id" @@ -849,7 +889,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_cardinality_String_notnull "select cardinality(kastr) from $not_nullable_tb order by id" order_qt_sql_cardinality_DatetimeV2 "select cardinality(kadtmv2) from $nullable_tb order by id" + order_qt_sql_cardinality_TimestampNs "select cardinality(cast(kadtmv2 as array)) from $nullable_tb order by id" order_qt_sql_cardinality_DatetimeV2_notnull "select cardinality(kadtmv2) from $not_nullable_tb order by id" + order_qt_sql_cardinality_TimestampNs_notnull "select cardinality(cast(kadtmv2 as array)) from $not_nullable_tb order by id" order_qt_sql_cardinality_DateV2 "select cardinality(kadtv2) from $nullable_tb order by id" order_qt_sql_cardinality_DateV2_notnull "select cardinality(kadtv2) from $not_nullable_tb order by id" @@ -882,7 +924,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_array_size_String_notnull "select array_size(kastr) from $not_nullable_tb order by id" order_qt_sql_array_size_DatetimeV2 "select array_size(kadtmv2) from $nullable_tb order by id" + order_qt_sql_array_size_TimestampNs "select array_size(cast(kadtmv2 as array)) from $nullable_tb order by id" order_qt_sql_array_size_DatetimeV2_notnull "select array_size(kadtmv2) from $not_nullable_tb order by id" + order_qt_sql_array_size_TimestampNs_notnull "select array_size(cast(kadtmv2 as array)) from $not_nullable_tb order by id" order_qt_sql_array_size_DateV2 "select array_size(kadtv2) from $nullable_tb order by id" order_qt_sql_array_size_DateV2_notnull "select array_size(kadtv2) from $not_nullable_tb order by id" @@ -915,7 +959,9 @@ suite("nereids_scalar_fn_Array1") { order_qt_sql_size_String_notnull "select size(kastr) from $not_nullable_tb order by id" order_qt_sql_size_DatetimeV2 "select size(kadtmv2) from $nullable_tb order by id" + order_qt_sql_size_TimestampNs "select size(cast(kadtmv2 as array)) from $nullable_tb order by id" order_qt_sql_size_DatetimeV2_notnull "select size(kadtmv2) from $not_nullable_tb order by id" + order_qt_sql_size_TimestampNs_notnull "select size(cast(kadtmv2 as array)) from $not_nullable_tb order by id" order_qt_sql_size_DateV2 "select size(kadtv2) from $nullable_tb order by id" order_qt_sql_size_DateV2_notnull "select size(kadtv2) from $not_nullable_tb order by id" diff --git a/regression-test/suites/nereids_function_p0/scalar_function/Array2.groovy b/regression-test/suites/nereids_function_p0/scalar_function/Array2.groovy index 4a6b890c04a2e0..20e29185f7646c 100644 --- a/regression-test/suites/nereids_function_p0/scalar_function/Array2.groovy +++ b/regression-test/suites/nereids_function_p0/scalar_function/Array2.groovy @@ -170,6 +170,12 @@ suite("nereids_scalar_fn_Array2") { WHEN x = y THEN 0 ELSE -1 END, arr) FROM (SELECT array_agg(kdtmv2s3) AS arr FROM fn_test)t""" order_qt_sql_array_sort_DatetimeV2_notnull """SELECT array_sort((x, y) -> IF(x < y, 1, IF(x = y, 0, -1)), arr) FROM (SELECT array_agg(kdtmv2s3) AS arr FROM fn_test_not_nullable)t""" + order_qt_sql_array_sort_TimestampNs """SELECT array_sort((x, y) -> CASE WHEN x IS NULL THEN -1 + WHEN y IS NULL THEN 1 + WHEN x < y THEN 1 + WHEN x = y THEN 0 + ELSE -1 END, arr) FROM (SELECT array_agg(cast(kdtmv2s3 as timestamp_ns)) AS arr FROM fn_test)t""" + order_qt_sql_array_sort_TimestampNs_notnull """SELECT array_sort((x, y) -> IF(x < y, 1, IF(x = y, 0, -1)), arr) FROM (SELECT array_agg(cast(kdtmv2s3 as timestamp_ns)) AS arr FROM fn_test_not_nullable)t""" order_qt_sql_array_sort_Boolean """SELECT array_sort((x, y) -> CASE WHEN x IS NULL THEN -1 WHEN y IS NULL THEN 1 WHEN x < y THEN 1 @@ -429,6 +435,18 @@ suite("nereids_scalar_fn_Array2") { ORDER BY id """ + order_qt_sql_array_sort_lambda_multir_timestamp_ns """ + SELECT id, array_sort( + (x, y) -> CASE WHEN x IS NULL THEN -1 + WHEN y IS NULL THEN 1 + WHEN x < y THEN 1 + WHEN x = y THEN 0 + ELSE -1 END, + cast(kadtmv2 as array)) + FROM fn_test_array_sort + ORDER BY id + """ + order_qt_sql_array_sort_lambda_multir_char """ SELECT id, array_sort( (x, y) -> CASE WHEN x IS NULL THEN -1 diff --git a/regression-test/suites/nereids_function_p0/scalar_function/C.groovy b/regression-test/suites/nereids_function_p0/scalar_function/C.groovy index 0a14602eff9c17..6e3ff6e04bd416 100644 --- a/regression-test/suites/nereids_function_p0/scalar_function/C.groovy +++ b/regression-test/suites/nereids_function_p0/scalar_function/C.groovy @@ -60,7 +60,9 @@ suite("nereids_scalar_fn_C") { qt_sql_coalesce_Date "select coalesce(kdt) from fn_test order by kdt" qt_sql_coalesce_Date_notnull "select coalesce(kdt) from fn_test_not_nullable order by kdt" qt_sql_coalesce_DateTimeV2 "select coalesce(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_coalesce_TimestampNs "select coalesce(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_coalesce_DateTimeV2_notnull "select coalesce(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_coalesce_TimestampNs_notnull "select coalesce(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_coalesce_DateV2 "select coalesce(kdtv2) from fn_test order by kdtv2" qt_sql_coalesce_DateV2_notnull "select coalesce(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_coalesce_DecimalV2 "select coalesce(kdcmls1) from fn_test order by kdcmls1" @@ -94,7 +96,9 @@ suite("nereids_scalar_fn_C") { qt_sql_convert_tz_DateTime_Varchar_Varchar "select convert_tz(kdtm, 'Asia/Shanghai', 'Europe/Sofia') from fn_test order by kdtm" qt_sql_convert_tz_DateTime_Varchar_Varchar_notnull "select convert_tz(kdtm, 'Asia/Shanghai', 'Europe/Sofia') from fn_test_not_nullable order by kdtm" qt_sql_convert_tz_DateTimeV2_Varchar_Varchar "select convert_tz(kdtmv2s1, 'Asia/Shanghai', 'Europe/Sofia') from fn_test order by kdtmv2s1" + qt_sql_convert_tz_TimestampNs_Varchar_Varchar "select convert_tz(cast(kdtmv2s1 as timestamp_ns), 'Asia/Shanghai', 'Europe/Sofia') from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_convert_tz_DateTimeV2_Varchar_Varchar_notnull "select convert_tz(kdtmv2s1, 'Asia/Shanghai', 'Europe/Sofia') from fn_test_not_nullable order by kdtmv2s1" + qt_sql_convert_tz_TimestampNs_Varchar_Varchar_notnull "select convert_tz(cast(kdtmv2s1 as timestamp_ns), 'Asia/Shanghai', 'Europe/Sofia') from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_cos_Double "select cos(kdbl) from fn_test order by kdbl" qt_sql_cos_Double_notnull "select cos(kdbl) from fn_test_not_nullable order by kdbl" qt_sql_cosh_Double "select cosh(kdbl) from fn_test order by kdbl" @@ -184,7 +188,9 @@ suite("nereids_scalar_fn_C") { qt_kadtv2 "select count(kadtv2) from fn_test " qt_kadtv2_not_nullable "select count(kadtv2) from fn_test_not_nullable " qt_kadtmv2 "select count(kadtmv2) from fn_test " + qt_kadtmv2_timestamp_ns "select count(cast(kadtmv2 as array)) from fn_test " qt_kadtmv2_not_nullable "select count(kadtmv2) from fn_test_not_nullable " + qt_kadtmv2_not_nullable_timestamp_ns "select count(cast(kadtmv2 as array)) from fn_test_not_nullable " qt_kachr "select count(kachr) from fn_test " qt_kachr_not_nullable "select count(kachr) from fn_test_not_nullable " qt_kavchr "select count(kavchr) from fn_test " diff --git a/regression-test/suites/nereids_function_p0/scalar_function/D.groovy b/regression-test/suites/nereids_function_p0/scalar_function/D.groovy index 009f101e2799d3..0eae6409418ff8 100644 --- a/regression-test/suites/nereids_function_p0/scalar_function/D.groovy +++ b/regression-test/suites/nereids_function_p0/scalar_function/D.groovy @@ -24,19 +24,25 @@ suite("nereids_scalar_fn_D") { qt_sql_date_DateTime "select date(kdtm) from fn_test order by kdtm" qt_sql_date_DateTime_notnull "select date(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_date_DateTimeV2 "select date(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_date_TimestampNs "select date(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_date_DateTimeV2_notnull "select date(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_date_TimestampNs_notnull "select date(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_date_format_DateTime_Varchar "select date_format(kdtm, '2006-01-02 12:00:00') from fn_test order by kdtm" qt_sql_date_format_DateTime_Varchar_notnull "select date_format(kdtm, '2006-01-02 12:00:00') from fn_test_not_nullable order by kdtm" qt_sql_date_format_Date_Varchar "select date_format(kdt, '2006-01-02') from fn_test order by kdt" qt_sql_date_format_Date_Varchar_notnull "select date_format(kdt, '2006-01-02') from fn_test_not_nullable order by kdt" qt_sql_date_format_DateTimeV2_Varchar "select date_format(kdtmv2s1, '2006-01-02 12:00:00') from fn_test order by kdtmv2s1" + qt_sql_date_format_TimestampNs_Varchar "select date_format(cast(kdtmv2s1 as timestamp_ns), '2006-01-02 12:00:00') from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_date_format_DateTimeV2_Varchar_notnull "select date_format(kdtmv2s1, '2006-01-02 12:00:00') from fn_test_not_nullable order by kdtmv2s1" + qt_sql_date_format_TimestampNs_Varchar_notnull "select date_format(cast(kdtmv2s1 as timestamp_ns), '2006-01-02 12:00:00') from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_date_format_DateV2_Varchar "select date_format(kdtv2, '2006-01-02') from fn_test order by kdtv2" qt_sql_date_format_DateV2_Varchar_notnull "select date_format(kdtv2, '2006-01-02') from fn_test_not_nullable order by kdtv2" qt_sql_date_trunc_DateTime_Varchar "select date_trunc(kdtm, 'year') from fn_test order by kdtm, kvchrs1" qt_sql_date_trunc_DateTime_Varchar_notnull "select date_trunc(kdtm, 'month') from fn_test_not_nullable order by kdtm, kvchrs1" qt_sql_date_trunc_DateTimeV2_Varchar "select date_trunc(kdtmv2s1, 'day') from fn_test order by kdtmv2s1, kvchrs1" + qt_sql_date_trunc_TimestampNs_Varchar "select date_trunc(cast(kdtmv2s1 as timestamp_ns), 'day') from fn_test order by cast(kdtmv2s1 as timestamp_ns), kvchrs1" qt_sql_date_trunc_DateTimeV2_Varchar_notnull "select date_trunc(kdtmv2s1, 'hour') from fn_test_not_nullable order by kdtmv2s1, kvchrs1" + qt_sql_date_trunc_TimestampNs_Varchar_notnull "select date_trunc(cast(kdtmv2s1 as timestamp_ns), 'hour') from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kvchrs1" qt_sql_date_trunc_Date_Varchar "select date_trunc(kdt, 'month') from fn_test order by kdt, kvchrs1" qt_sql_date_trunc_Date_Varchar_notnull "select date_trunc(kdt, 'week') from fn_test_not_nullable order by kdt, kvchrs1" qt_sql_date_trunc_DateV2_Varchar "select date_trunc(kdtv2, 'day') from fn_test order by kdtv2, kvchrs1" @@ -44,15 +50,23 @@ suite("nereids_scalar_fn_D") { qt_sql_datediff_DateTime_DateTime "select datediff(kdtm, kdtm) from fn_test order by kdtm, kdtm" qt_sql_datediff_DateTime_DateTime_notnull "select datediff(kdtm, kdtm) from fn_test_not_nullable order by kdtm, kdtm" qt_sql_datediff_DateTimeV2_DateTimeV2 "select datediff(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_datediff_TimestampNs_TimestampNs "select datediff(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_datediff_DateTimeV2_DateTimeV2_notnull "select datediff(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_datediff_TimestampNs_TimestampNs_notnull "select datediff(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_datediff_DateTimeV2_DateV2 "select datediff(kdtmv2s1, kdtv2) from fn_test order by kdtmv2s1, kdtv2" + qt_sql_datediff_TimestampNs_DateV2 "select datediff(cast(kdtmv2s1 as timestamp_ns), kdtv2) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kdtv2" qt_sql_datediff_DateTimeV2_DateV2_notnull "select datediff(kdtmv2s1, kdtv2) from fn_test_not_nullable order by kdtmv2s1, kdtv2" + qt_sql_datediff_TimestampNs_DateV2_notnull "select datediff(cast(kdtmv2s1 as timestamp_ns), kdtv2) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kdtv2" qt_sql_datediff_DateV2_DateTimeV2 "select datediff(kdtv2, kdtmv2s1) from fn_test order by kdtv2, kdtmv2s1" + qt_sql_datediff_DateV2_TimestampNs "select datediff(kdtv2, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by kdtv2, cast(kdtmv2s1 as timestamp_ns)" qt_sql_datediff_DateV2_DateTimeV2_notnull "select datediff(kdtv2, kdtmv2s1) from fn_test_not_nullable order by kdtv2, kdtmv2s1" + qt_sql_datediff_DateV2_TimestampNs_notnull "select datediff(kdtv2, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by kdtv2, cast(kdtmv2s1 as timestamp_ns)" qt_sql_datediff_DateV2_DateV2 "select datediff(kdtv2, kdtv2) from fn_test order by kdtv2, kdtv2" qt_sql_datediff_DateV2_DateV2_notnull "select datediff(kdtv2, kdtv2) from fn_test_not_nullable order by kdtv2, kdtv2" qt_sql_datediff_DateTimeV2_DateTime "select datediff(kdtmv2s1, kdtm) from fn_test order by kdtmv2s1, kdtm" + qt_sql_datediff_TimestampNs_DateTime "select datediff(cast(kdtmv2s1 as timestamp_ns), kdtm) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kdtm" qt_sql_datediff_DateTimeV2_DateTime_notnull "select datediff(kdtmv2s1, kdtm) from fn_test_not_nullable order by kdtmv2s1, kdtm" + qt_sql_datediff_TimestampNs_DateTime_notnull "select datediff(cast(kdtmv2s1 as timestamp_ns), kdtm) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kdtm" qt_sql_datediff_DateV2_DateTime "select datediff(kdtv2, kdtm) from fn_test order by kdtv2, kdtm" qt_sql_datediff_DateV2_DateTime_notnull "select datediff(kdtv2, kdtm) from fn_test_not_nullable order by kdtv2, kdtm" def timeZoneOrigValue = sql("select @@time_zone") @@ -169,11 +183,15 @@ suite("nereids_scalar_fn_D") { sql "set time_zone = '${timeZoneOrigValue[0][0]}'" } qt_sql_datev2_DateTimeV2 "select datev2(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_datev2_TimestampNs "select datev2(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_datev2_DateTimeV2_notnull "select datev2(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_datev2_TimestampNs_notnull "select datev2(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_day_ceil_DateTime "select day_ceil(kdtm) from fn_test order by kdtm" qt_sql_day_ceil_DateTime_notnull "select day_ceil(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_day_ceil_DateTimeV2 "select day_ceil(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_day_ceil_TimestampNs "select day_ceil(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_day_ceil_DateTimeV2_notnull "select day_ceil(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_day_ceil_TimestampNs_notnull "select day_ceil(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_day_ceil_DateV2 "select day_ceil(kdtv2) from fn_test order by kdtv2" qt_sql_day_ceil_DateV2_notnull "select day_ceil(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_day_ceil_DateTime_DateTime "select day_ceil(kdtm, kdtm) from fn_test order by kdtm, kdtm" @@ -181,9 +199,13 @@ suite("nereids_scalar_fn_D") { qt_sql_day_ceil_DateTime_Integer "select day_ceil(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_day_ceil_DateTime_Integer_notnull "select day_ceil(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_day_ceil_DateTimeV2_DateTimeV2 "select day_ceil(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_day_ceil_TimestampNs_TimestampNs "select day_ceil(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_day_ceil_DateTimeV2_DateTimeV2_notnull "select day_ceil(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_day_ceil_TimestampNs_TimestampNs_notnull "select day_ceil(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_day_ceil_DateTimeV2_Integer "select day_ceil(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_day_ceil_TimestampNs_Integer "select day_ceil(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_day_ceil_DateTimeV2_Integer_notnull "select day_ceil(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_day_ceil_TimestampNs_Integer_notnull "select day_ceil(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_day_ceil_DateV2_DateV2 "select day_ceil(kdtv2, kdtv2) from fn_test order by kdtv2, kdtv2" qt_sql_day_ceil_DateV2_DateV2_notnull "select day_ceil(kdtv2, kdtv2) from fn_test_not_nullable order by kdtv2, kdtv2" qt_sql_day_ceil_DateV2_Integer "select day_ceil(kdtv2, kint) from fn_test order by kdtv2, kint" @@ -191,13 +213,17 @@ suite("nereids_scalar_fn_D") { qt_sql_day_ceil_DateTime_Integer_DateTime "select day_ceil(kdtm, kint, kdtm) from fn_test order by kdtm, kint, kdtm" qt_sql_day_ceil_DateTime_Integer_DateTime_notnull "select day_ceil(kdtm, kint, kdtm) from fn_test_not_nullable order by kdtm, kint, kdtm" qt_sql_day_ceil_DateTimeV2_Integer_DateTimeV2 "select day_ceil(kdtmv2s1, kint, kdtmv2s1) from fn_test order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_day_ceil_TimestampNs_Integer_TimestampNs "select day_ceil(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_day_ceil_DateTimeV2_Integer_DateTimeV2_notnull "select day_ceil(kdtmv2s1, kint, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_day_ceil_TimestampNs_Integer_TimestampNs_notnull "select day_ceil(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_day_ceil_DateV2_Integer_DateV2 "select day_ceil(kdtv2, kint, kdtv2) from fn_test order by kdtv2, kint, kdtv2" qt_sql_day_ceil_DateV2_Integer_DateV2_notnull "select day_ceil(kdtv2, kint, kdtv2) from fn_test_not_nullable order by kdtv2, kint, kdtv2" qt_sql_day_floor_DateTime "select day_floor(kdtm) from fn_test order by kdtm" qt_sql_day_floor_DateTime_notnull "select day_floor(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_day_floor_DateTimeV2 "select day_floor(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_day_floor_TimestampNs "select day_floor(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_day_floor_DateTimeV2_notnull "select day_floor(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_day_floor_TimestampNs_notnull "select day_floor(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_day_floor_DateV2 "select day_floor(kdtv2) from fn_test order by kdtv2" qt_sql_day_floor_DateV2_notnull "select day_floor(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_day_floor_DateTime_DateTime "select day_floor(kdtm, kdtm) from fn_test order by kdtm, kdtm" @@ -205,9 +231,13 @@ suite("nereids_scalar_fn_D") { qt_sql_day_floor_DateTime_Integer "select day_floor(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_day_floor_DateTime_Integer_notnull "select day_floor(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_day_floor_DateTimeV2_DateTimeV2 "select day_floor(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_day_floor_TimestampNs_TimestampNs "select day_floor(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_day_floor_DateTimeV2_DateTimeV2_notnull "select day_floor(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_day_floor_TimestampNs_TimestampNs_notnull "select day_floor(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_day_floor_DateTimeV2_Integer "select day_floor(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_day_floor_TimestampNs_Integer "select day_floor(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_day_floor_DateTimeV2_Integer_notnull "select day_floor(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_day_floor_TimestampNs_Integer_notnull "select day_floor(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_day_floor_DateV2_DateV2 "select day_floor(kdtv2, kdtv2) from fn_test order by kdtv2, kdtv2" qt_sql_day_floor_DateV2_DateV2_notnull "select day_floor(kdtv2, kdtv2) from fn_test_not_nullable order by kdtv2, kdtv2" qt_sql_day_floor_DateV2_Integer "select day_floor(kdtv2, kint) from fn_test order by kdtv2, kint" @@ -215,35 +245,47 @@ suite("nereids_scalar_fn_D") { qt_sql_day_floor_DateTime_Integer_DateTime "select day_floor(kdtm, kint, kdtm) from fn_test order by kdtm, kint, kdtm" qt_sql_day_floor_DateTime_Integer_DateTime_notnull "select day_floor(kdtm, kint, kdtm) from fn_test_not_nullable order by kdtm, kint, kdtm" qt_sql_day_floor_DateTimeV2_Integer_DateTimeV2 "select day_floor(kdtmv2s1, kint, kdtmv2s1) from fn_test order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_day_floor_TimestampNs_Integer_TimestampNs "select day_floor(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_day_floor_DateTimeV2_Integer_DateTimeV2_notnull "select day_floor(kdtmv2s1, kint, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_day_floor_TimestampNs_Integer_TimestampNs_notnull "select day_floor(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_day_floor_DateV2_Integer_DateV2 "select day_floor(kdtv2, kint, kdtv2) from fn_test order by kdtv2, kint, kdtv2" qt_sql_day_floor_DateV2_Integer_DateV2_notnull "select day_floor(kdtv2, kint, kdtv2) from fn_test_not_nullable order by kdtv2, kint, kdtv2" qt_sql_dayname_DateTime "select dayname(kdtm) from fn_test order by kdtm" qt_sql_dayname_DateTime_notnull "select dayname(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_dayname_DateTimeV2 "select dayname(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_dayname_TimestampNs "select dayname(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_dayname_DateTimeV2_notnull "select dayname(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_dayname_TimestampNs_notnull "select dayname(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_dayname_DateV2 "select dayname(kdtv2) from fn_test order by kdtv2" qt_sql_dayname_DateV2_notnull "select dayname(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_dayofmonth_DateTime "select dayofmonth(kdtm) from fn_test order by kdtm" qt_sql_dayofmonth_DateTime_notnull "select dayofmonth(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_dayofmonth_DateTimeV2 "select dayofmonth(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_dayofmonth_TimestampNs "select dayofmonth(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_dayofmonth_DateTimeV2_notnull "select dayofmonth(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_dayofmonth_TimestampNs_notnull "select dayofmonth(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_dayofmonth_DateV2 "select dayofmonth(kdtv2) from fn_test order by kdtv2" qt_sql_dayofmonth_DateV2_notnull "select dayofmonth(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_dayofweek_DateTime "select dayofweek(kdtm) from fn_test order by kdtm" qt_sql_dayofweek_DateTime_notnull "select dayofweek(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_dayofweek_DateTimeV2 "select dayofweek(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_dayofweek_TimestampNs "select dayofweek(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_dayofweek_DateTimeV2_notnull "select dayofweek(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_dayofweek_TimestampNs_notnull "select dayofweek(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_dayofweek_DateV2 "select dayofweek(kdtv2) from fn_test order by kdtv2" qt_sql_dayofweek_DateV2_notnull "select dayofweek(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_dayofyear_DateTime "select dayofyear(kdtm) from fn_test order by kdtm" qt_sql_dayofyear_DateTime_notnull "select dayofyear(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_dayofyear_DateTimeV2 "select dayofyear(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_dayofyear_TimestampNs "select dayofyear(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_dayofyear_DateTimeV2_notnull "select dayofyear(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_dayofyear_TimestampNs_notnull "select dayofyear(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_dayofyear_DateV2 "select dayofyear(kdtv2) from fn_test order by kdtv2" qt_sql_dayofyear_DateV2_notnull "select dayofyear(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_days_add_DateTimeV2_Integer "select days_add(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_days_add_TimestampNs_Integer "select days_add(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_days_add_DateTimeV2_Integer_notnull "select days_add(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_days_add_TimestampNs_Integer_notnull "select days_add(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_days_add_DateV2_Integer "select days_add(kdtv2, kint) from fn_test order by kdtv2, kint" qt_sql_days_add_DateV2_Integer_notnull "select days_add(kdtv2, kint) from fn_test_not_nullable order by kdtv2, kint" qt_sql_days_add_DateTime_Integer "select days_add(kdtm, kint) from fn_test order by kdtm, kint" @@ -261,11 +303,17 @@ suite("nereids_scalar_fn_D") { qt_sql_days_diff_DateTime_DateTime "select days_diff(kdtm, kdtm) from fn_test order by kdtm, kdtm" qt_sql_days_diff_DateTime_DateTime_notnull "select days_diff(kdtm, kdtm) from fn_test_not_nullable order by kdtm, kdtm" qt_sql_days_diff_DateTimeV2_DateTimeV2 "select days_diff(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_days_diff_TimestampNs_TimestampNs "select days_diff(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_days_diff_DateTimeV2_DateTimeV2_notnull "select days_diff(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_days_diff_TimestampNs_TimestampNs_notnull "select days_diff(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_days_diff_DateV2_DateTimeV2 "select days_diff(kdtv2, kdtmv2s1) from fn_test order by kdtv2, kdtmv2s1" + qt_sql_days_diff_DateV2_TimestampNs "select days_diff(kdtv2, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by kdtv2, cast(kdtmv2s1 as timestamp_ns)" qt_sql_days_diff_DateV2_DateTimeV2_notnull "select days_diff(kdtv2, kdtmv2s1) from fn_test_not_nullable order by kdtv2, kdtmv2s1" + qt_sql_days_diff_DateV2_TimestampNs_notnull "select days_diff(kdtv2, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by kdtv2, cast(kdtmv2s1 as timestamp_ns)" qt_sql_days_diff_DateTimeV2_DateV2 "select days_diff(kdtmv2s1, kdtv2) from fn_test order by kdtmv2s1, kdtv2" + qt_sql_days_diff_TimestampNs_DateV2 "select days_diff(cast(kdtmv2s1 as timestamp_ns), kdtv2) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kdtv2" qt_sql_days_diff_DateTimeV2_DateV2_notnull "select days_diff(kdtmv2s1, kdtv2) from fn_test_not_nullable order by kdtmv2s1, kdtv2" + qt_sql_days_diff_TimestampNs_DateV2_notnull "select days_diff(cast(kdtmv2s1 as timestamp_ns), kdtv2) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kdtv2" qt_sql_days_diff_DateV2_DateV2 "select days_diff(kdtv2, kdtv2) from fn_test order by kdtv2, kdtv2" qt_sql_days_diff_DateV2_DateV2_notnull "select days_diff(kdtv2, kdtv2) from fn_test_not_nullable order by kdtv2, kdtv2" qt_sql_days_diff_DateV2_DateTime "select days_diff(kdtv2, kdtm) from fn_test order by kdtv2, kdtm" @@ -273,11 +321,17 @@ suite("nereids_scalar_fn_D") { qt_sql_days_diff_DateTime_DateV2 "select days_diff(kdtm, kdtv2) from fn_test order by kdtm, kdtv2" qt_sql_days_diff_DateTime_DateV2_notnull "select days_diff(kdtm, kdtv2) from fn_test_not_nullable order by kdtm, kdtv2" qt_sql_days_diff_DateTimeV2_DateTime "select days_diff(kdtmv2s1, kdtm) from fn_test order by kdtmv2s1, kdtm" + qt_sql_days_diff_TimestampNs_DateTime "select days_diff(cast(kdtmv2s1 as timestamp_ns), kdtm) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kdtm" qt_sql_days_diff_DateTimeV2_DateTime_notnull "select days_diff(kdtmv2s1, kdtm) from fn_test_not_nullable order by kdtmv2s1, kdtm" + qt_sql_days_diff_TimestampNs_DateTime_notnull "select days_diff(cast(kdtmv2s1 as timestamp_ns), kdtm) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kdtm" qt_sql_days_diff_DateTime_DateTimeV2 "select days_diff(kdtm, kdtmv2s1) from fn_test order by kdtm, kdtmv2s1" + qt_sql_days_diff_DateTime_TimestampNs "select days_diff(kdtm, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by kdtm, cast(kdtmv2s1 as timestamp_ns)" qt_sql_days_diff_DateTime_DateTimeV2_notnull "select days_diff(kdtm, kdtmv2s1) from fn_test_not_nullable order by kdtm, kdtmv2s1" + qt_sql_days_diff_DateTime_TimestampNs_notnull "select days_diff(kdtm, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by kdtm, cast(kdtmv2s1 as timestamp_ns)" qt_sql_days_sub_DateTimeV2_Integer "select days_sub(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_days_sub_TimestampNs_Integer "select days_sub(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_days_sub_DateTimeV2_Integer_notnull "select days_sub(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_days_sub_TimestampNs_Integer_notnull "select days_sub(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_days_sub_DateV2_Integer "select days_sub(kdtv2, kint) from fn_test order by kdtv2, kint" qt_sql_days_sub_DateV2_Integer_notnull "select days_sub(kdtv2, kint) from fn_test_not_nullable order by kdtv2, kint" qt_sql_days_sub_DateTime_Integer "select days_sub(kdtm, kint) from fn_test order by kdtm, kint" diff --git a/regression-test/suites/nereids_function_p0/scalar_function/F.groovy b/regression-test/suites/nereids_function_p0/scalar_function/F.groovy index a89f3dc9ea535e..e583073609cc40 100644 --- a/regression-test/suites/nereids_function_p0/scalar_function/F.groovy +++ b/regression-test/suites/nereids_function_p0/scalar_function/F.groovy @@ -38,7 +38,9 @@ suite("nereids_scalar_fn_F") { qt_sql_field_DateV2 "select field(kdtv2, 1, 2) from fn_test order by kdtv2" qt_sql_field_DateV2_notnull "select field(kdtv2, 1, 2) from fn_test_not_nullable order by kdtv2" qt_sql_field_DateTimeV2 "select field(kdtmv2s1, 1, 2) from fn_test order by kdtmv2s1" + qt_sql_field_TimestampNs "select field(cast(kdtmv2s1 as timestamp_ns), 1, 2) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_field_DateTimeV2_notnull "select field(kdtmv2s1, 1, 2) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_field_TimestampNs_notnull "select field(cast(kdtmv2s1 as timestamp_ns), 1, 2) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_field_Varchar "select field(kvchrs1, 1, 2) from fn_test order by kvchrs1" qt_sql_field_Varchar_notnull "select field(kvchrs1, 1, 2) from fn_test_not_nullable order by kvchrs1" qt_sql_field_String "select field(kstr, 1, 2) from fn_test order by kstr" diff --git a/regression-test/suites/nereids_function_p0/scalar_function/G.groovy b/regression-test/suites/nereids_function_p0/scalar_function/G.groovy index a8eb682daa1abf..1539f84de0221f 100644 --- a/regression-test/suites/nereids_function_p0/scalar_function/G.groovy +++ b/regression-test/suites/nereids_function_p0/scalar_function/G.groovy @@ -53,7 +53,9 @@ suite("nereids_scalar_fn_G") { qt_sql_greatest_DateTime "select greatest(kdtm) from fn_test order by kdtm" qt_sql_greatest_DateTime_notnull "select greatest(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_greatest_DateTimeV2 "select greatest(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_greatest_TimestampNs "select greatest(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_greatest_DateTimeV2_notnull "select greatest(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_greatest_TimestampNs_notnull "select greatest(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_greatest_Varchar "select greatest(kvchrs1) from fn_test order by kvchrs1" qt_sql_greatest_Varchar_notnull "select greatest(kvchrs1) from fn_test_not_nullable order by kvchrs1" qt_sql_greatest_String "select greatest(kstr) from fn_test order by kstr" diff --git a/regression-test/suites/nereids_function_p0/scalar_function/H.groovy b/regression-test/suites/nereids_function_p0/scalar_function/H.groovy index 08d6f9f92baf59..3fbfcce8778acb 100644 --- a/regression-test/suites/nereids_function_p0/scalar_function/H.groovy +++ b/regression-test/suites/nereids_function_p0/scalar_function/H.groovy @@ -40,45 +40,65 @@ suite("nereids_scalar_fn_H") { qt_sql_hour_DateTime "select hour(kdtm) from fn_test order by kdtm" qt_sql_hour_DateTime_notnull "select hour(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_hour_DateTimeV2 "select hour(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_hour_TimestampNs "select hour(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_hour_DateTimeV2_notnull "select hour(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_hour_TimestampNs_notnull "select hour(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_hour_DateV2 "select hour(kdtv2) from fn_test order by kdtv2" qt_sql_hour_DateV2_notnull "select hour(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_hour_ceil_DateTime "select hour_ceil(kdtm) from fn_test order by kdtm" qt_sql_hour_ceil_DateTime_notnull "select hour_ceil(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_hour_ceil_DateTimeV2 "select hour_ceil(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_hour_ceil_TimestampNs "select hour_ceil(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_hour_ceil_DateTimeV2_notnull "select hour_ceil(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_hour_ceil_TimestampNs_notnull "select hour_ceil(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_hour_ceil_DateTime_DateTime "select hour_ceil(kdtm, kdtm) from fn_test order by kdtm, kdtm" qt_sql_hour_ceil_DateTime_DateTime_notnull "select hour_ceil(kdtm, kdtm) from fn_test_not_nullable order by kdtm, kdtm" qt_sql_hour_ceil_DateTime_Integer "select hour_ceil(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_hour_ceil_DateTime_Integer_notnull "select hour_ceil(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_hour_ceil_DateTimeV2_DateTimeV2 "select hour_ceil(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_hour_ceil_TimestampNs_TimestampNs "select hour_ceil(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_hour_ceil_DateTimeV2_DateTimeV2_notnull "select hour_ceil(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_hour_ceil_TimestampNs_TimestampNs_notnull "select hour_ceil(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_hour_ceil_DateTimeV2_Integer "select hour_ceil(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_hour_ceil_TimestampNs_Integer "select hour_ceil(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_hour_ceil_DateTimeV2_Integer_notnull "select hour_ceil(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_hour_ceil_TimestampNs_Integer_notnull "select hour_ceil(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_hour_ceil_DateTime_Integer_DateTime "select hour_ceil(kdtm, kint, kdtm) from fn_test order by kdtm, kint, kdtm" qt_sql_hour_ceil_DateTime_Integer_DateTime_notnull "select hour_ceil(kdtm, kint, kdtm) from fn_test_not_nullable order by kdtm, kint, kdtm" qt_sql_hour_ceil_DateTimeV2_Integer_DateTimeV2 "select hour_ceil(kdtmv2s1, kint, kdtmv2s1) from fn_test order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_hour_ceil_TimestampNs_Integer_TimestampNs "select hour_ceil(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_hour_ceil_DateTimeV2_Integer_DateTimeV2_notnull "select hour_ceil(kdtmv2s1, kint, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_hour_ceil_TimestampNs_Integer_TimestampNs_notnull "select hour_ceil(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_hour_floor_DateTime "select hour_floor(kdtm) from fn_test order by kdtm" qt_sql_hour_floor_DateTime_notnull "select hour_floor(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_hour_floor_DateTimeV2 "select hour_floor(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_hour_floor_TimestampNs "select hour_floor(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_hour_floor_DateTimeV2_notnull "select hour_floor(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_hour_floor_TimestampNs_notnull "select hour_floor(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_hour_floor_DateTime_DateTime "select hour_floor(kdtm, kdtm) from fn_test order by kdtm, kdtm" qt_sql_hour_floor_DateTime_DateTime_notnull "select hour_floor(kdtm, kdtm) from fn_test_not_nullable order by kdtm, kdtm" qt_sql_hour_floor_DateTime_Integer "select hour_floor(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_hour_floor_DateTime_Integer_notnull "select hour_floor(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_hour_floor_DateTimeV2_DateTimeV2 "select hour_floor(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_hour_floor_TimestampNs_TimestampNs "select hour_floor(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_hour_floor_DateTimeV2_DateTimeV2_notnull "select hour_floor(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_hour_floor_TimestampNs_TimestampNs_notnull "select hour_floor(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_hour_floor_DateTimeV2_Integer "select hour_floor(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_hour_floor_TimestampNs_Integer "select hour_floor(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_hour_floor_DateTimeV2_Integer_notnull "select hour_floor(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_hour_floor_TimestampNs_Integer_notnull "select hour_floor(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_hour_floor_DateTime_Integer_DateTime "select hour_floor(kdtm, kint, kdtm) from fn_test order by kdtm, kint, kdtm" qt_sql_hour_floor_DateTime_Integer_DateTime_notnull "select hour_floor(kdtm, kint, kdtm) from fn_test_not_nullable order by kdtm, kint, kdtm" qt_sql_hour_floor_DateTimeV2_Integer_DateTimeV2 "select hour_floor(kdtmv2s1, kint, kdtmv2s1) from fn_test order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_hour_floor_TimestampNs_Integer_TimestampNs "select hour_floor(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_hour_floor_DateTimeV2_Integer_DateTimeV2_notnull "select hour_floor(kdtmv2s1, kint, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_hour_floor_TimestampNs_Integer_TimestampNs_notnull "select hour_floor(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_hours_add_DateTime_Integer "select hours_add(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_hours_add_DateTime_Integer_notnull "select hours_add(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_hours_add_DateTimeV2_Integer "select hours_add(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_hours_add_TimestampNs_Integer "select hours_add(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_hours_add_DateTimeV2_Integer_notnull "select hours_add(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_hours_add_TimestampNs_Integer_notnull "select hours_add(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_hours_add_Date_Integer "select hours_add(kdt, kint) from fn_test order by kdt, kint" qt_sql_hours_add_Date_Integer_notnull "select hours_add(kdt, kint) from fn_test_not_nullable order by kdt, kint" qt_sql_hours_add_DateV2_Integer "select hours_add(kdtv2, kint) from fn_test order by kdtv2, kint" @@ -86,11 +106,17 @@ suite("nereids_scalar_fn_H") { qt_sql_hours_diff_DateTime_DateTime "select hours_diff(kdtm, kdtm) from fn_test order by kdtm, kdtm" qt_sql_hours_diff_DateTime_DateTime_notnull "select hours_diff(kdtm, kdtm) from fn_test_not_nullable order by kdtm, kdtm" qt_sql_hours_diff_DateTimeV2_DateTimeV2 "select hours_diff(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_hours_diff_TimestampNs_TimestampNs "select hours_diff(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_hours_diff_DateTimeV2_DateTimeV2_notnull "select hours_diff(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_hours_diff_TimestampNs_TimestampNs_notnull "select hours_diff(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_hours_diff_DateV2_DateTimeV2 "select hours_diff(kdtv2, kdtmv2s1) from fn_test order by kdtv2, kdtmv2s1" + qt_sql_hours_diff_DateV2_TimestampNs "select hours_diff(kdtv2, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by kdtv2, cast(kdtmv2s1 as timestamp_ns)" qt_sql_hours_diff_DateV2_DateTimeV2_notnull "select hours_diff(kdtv2, kdtmv2s1) from fn_test_not_nullable order by kdtv2, kdtmv2s1" + qt_sql_hours_diff_DateV2_TimestampNs_notnull "select hours_diff(kdtv2, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by kdtv2, cast(kdtmv2s1 as timestamp_ns)" qt_sql_hours_diff_DateTimeV2_DateV2 "select hours_diff(kdtmv2s1, kdtv2) from fn_test order by kdtmv2s1, kdtv2" + qt_sql_hours_diff_TimestampNs_DateV2 "select hours_diff(cast(kdtmv2s1 as timestamp_ns), kdtv2) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kdtv2" qt_sql_hours_diff_DateTimeV2_DateV2_notnull "select hours_diff(kdtmv2s1, kdtv2) from fn_test_not_nullable order by kdtmv2s1, kdtv2" + qt_sql_hours_diff_TimestampNs_DateV2_notnull "select hours_diff(cast(kdtmv2s1 as timestamp_ns), kdtv2) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kdtv2" qt_sql_hours_diff_DateV2_DateV2 "select hours_diff(kdtv2, kdtv2) from fn_test order by kdtv2, kdtv2" qt_sql_hours_diff_DateV2_DateV2_notnull "select hours_diff(kdtv2, kdtv2) from fn_test_not_nullable order by kdtv2, kdtv2" qt_sql_hours_diff_DateV2_DateTime "select hours_diff(kdtv2, kdtm) from fn_test order by kdtv2, kdtm" @@ -98,13 +124,19 @@ suite("nereids_scalar_fn_H") { qt_sql_hours_diff_DateTime_DateV2 "select hours_diff(kdtm, kdtv2) from fn_test order by kdtm, kdtv2" qt_sql_hours_diff_DateTime_DateV2_notnull "select hours_diff(kdtm, kdtv2) from fn_test_not_nullable order by kdtm, kdtv2" qt_sql_hours_diff_DateTimeV2_DateTime "select hours_diff(kdtmv2s1, kdtm) from fn_test order by kdtmv2s1, kdtm" + qt_sql_hours_diff_TimestampNs_DateTime "select hours_diff(cast(kdtmv2s1 as timestamp_ns), kdtm) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kdtm" qt_sql_hours_diff_DateTimeV2_DateTime_notnull "select hours_diff(kdtmv2s1, kdtm) from fn_test_not_nullable order by kdtmv2s1, kdtm" + qt_sql_hours_diff_TimestampNs_DateTime_notnull "select hours_diff(cast(kdtmv2s1 as timestamp_ns), kdtm) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kdtm" qt_sql_hours_diff_DateTime_DateTimeV2 "select hours_diff(kdtm, kdtmv2s1) from fn_test order by kdtm, kdtmv2s1" + qt_sql_hours_diff_DateTime_TimestampNs "select hours_diff(kdtm, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by kdtm, cast(kdtmv2s1 as timestamp_ns)" qt_sql_hours_diff_DateTime_DateTimeV2_notnull "select hours_diff(kdtm, kdtmv2s1) from fn_test_not_nullable order by kdtm, kdtmv2s1" + qt_sql_hours_diff_DateTime_TimestampNs_notnull "select hours_diff(kdtm, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by kdtm, cast(kdtmv2s1 as timestamp_ns)" qt_sql_hours_sub_DateTime_Integer "select hours_sub(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_hours_sub_DateTime_Integer_notnull "select hours_sub(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_hours_sub_DateTimeV2_Integer "select hours_sub(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_hours_sub_TimestampNs_Integer "select hours_sub(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_hours_sub_DateTimeV2_Integer_notnull "select hours_sub(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_hours_sub_TimestampNs_Integer_notnull "select hours_sub(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_hours_sub_Date_Integer "select hours_sub(kdt, kint) from fn_test order by kdt, kint" qt_sql_hours_sub_Date_Integer_notnull "select hours_sub(kdt, kint) from fn_test_not_nullable order by kdt, kint" qt_sql_hours_sub_DateV2_Integer "select hours_sub(kdtv2, kint) from fn_test order by kdtv2, kint" diff --git a/regression-test/suites/nereids_function_p0/scalar_function/L.groovy b/regression-test/suites/nereids_function_p0/scalar_function/L.groovy index daf28b3a8a9f34..c344ebdbec1a29 100644 --- a/regression-test/suites/nereids_function_p0/scalar_function/L.groovy +++ b/regression-test/suites/nereids_function_p0/scalar_function/L.groovy @@ -24,7 +24,9 @@ suite("nereids_scalar_fn_L") { qt_sql_last_day_Date "select last_day(kdt) from fn_test order by kdt" qt_sql_last_day_Date_notnull "select last_day(kdt) from fn_test_not_nullable order by kdt" qt_sql_last_day_DateTimeV2 "select last_day(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_last_day_TimestampNs "select last_day(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_last_day_DateTimeV2_notnull "select last_day(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_last_day_TimestampNs_notnull "select last_day(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_last_day_DateV2 "select last_day(kdtv2) from fn_test order by kdtv2" qt_sql_last_day_DateV2_notnull "select last_day(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_lcm_TinyInt_TinyInt "select lcm(ktint, ktint) from fn_test order by ktint, ktint" @@ -58,7 +60,9 @@ suite("nereids_scalar_fn_L") { qt_sql_least_DateTime "select least(kdtm) from fn_test order by kdtm" qt_sql_least_DateTime_notnull "select least(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_least_DateTimeV2 "select least(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_least_TimestampNs "select least(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_least_DateTimeV2_notnull "select least(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_least_TimestampNs_notnull "select least(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_least_DecimalV2 "select least(kdcmls1) from fn_test order by kdcmls1" qt_sql_least_DecimalV2_notnull "select least(kdcmls1) from fn_test_not_nullable order by kdcmls1" qt_sql_least_Varchar "select least(kvchrs1) from fn_test order by kvchrs1" diff --git a/regression-test/suites/nereids_function_p0/scalar_function/M.groovy b/regression-test/suites/nereids_function_p0/scalar_function/M.groovy index 7a70e78431f54d..0fa93ed01b29bc 100644 --- a/regression-test/suites/nereids_function_p0/scalar_function/M.groovy +++ b/regression-test/suites/nereids_function_p0/scalar_function/M.groovy @@ -52,45 +52,65 @@ suite("nereids_scalar_fn_M") { qt_sql_minute_DateTime "select minute(kdtm) from fn_test order by kdtm" qt_sql_minute_DateTime_notnull "select minute(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_minute_DateTimeV2 "select minute(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_minute_TimestampNs "select minute(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_minute_DateTimeV2_notnull "select minute(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_minute_TimestampNs_notnull "select minute(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_minute_DateV2 "select minute(kdtv2) from fn_test order by kdtv2" qt_sql_minute_DateV2_notnull "select minute(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_minute_ceil_DateTime "select minute_ceil(kdtm) from fn_test order by kdtm" qt_sql_minute_ceil_DateTime_notnull "select minute_ceil(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_minute_ceil_DateTimeV2 "select minute_ceil(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_minute_ceil_TimestampNs "select minute_ceil(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_minute_ceil_DateTimeV2_notnull "select minute_ceil(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_minute_ceil_TimestampNs_notnull "select minute_ceil(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_minute_ceil_DateTime_DateTime "select minute_ceil(kdtm, kdtm) from fn_test order by kdtm, kdtm" qt_sql_minute_ceil_DateTime_DateTime_notnull "select minute_ceil(kdtm, kdtm) from fn_test_not_nullable order by kdtm, kdtm" qt_sql_minute_ceil_DateTime_Integer "select minute_ceil(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_minute_ceil_DateTime_Integer_notnull "select minute_ceil(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_minute_ceil_DateTimeV2_DateTimeV2 "select minute_ceil(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_minute_ceil_TimestampNs_TimestampNs "select minute_ceil(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_minute_ceil_DateTimeV2_DateTimeV2_notnull "select minute_ceil(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_minute_ceil_TimestampNs_TimestampNs_notnull "select minute_ceil(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_minute_ceil_DateTimeV2_Integer "select minute_ceil(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_minute_ceil_TimestampNs_Integer "select minute_ceil(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_minute_ceil_DateTimeV2_Integer_notnull "select minute_ceil(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_minute_ceil_TimestampNs_Integer_notnull "select minute_ceil(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_minute_ceil_DateTime_Integer_DateTime "select minute_ceil(kdtm, kint, kdtm) from fn_test order by kdtm, kint, kdtm" qt_sql_minute_ceil_DateTime_Integer_DateTime_notnull "select minute_ceil(kdtm, kint, kdtm) from fn_test_not_nullable order by kdtm, kint, kdtm" qt_sql_minute_ceil_DateTimeV2_Integer_DateTimeV2 "select minute_ceil(kdtmv2s1, kint, kdtmv2s1) from fn_test order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_minute_ceil_TimestampNs_Integer_TimestampNs "select minute_ceil(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_minute_ceil_DateTimeV2_Integer_DateTimeV2_notnull "select minute_ceil(kdtmv2s1, kint, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_minute_ceil_TimestampNs_Integer_TimestampNs_notnull "select minute_ceil(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_minute_floor_DateTime "select minute_floor(kdtm) from fn_test order by kdtm" qt_sql_minute_floor_DateTime_notnull "select minute_floor(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_minute_floor_DateTimeV2 "select minute_floor(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_minute_floor_TimestampNs "select minute_floor(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_minute_floor_DateTimeV2_notnull "select minute_floor(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_minute_floor_TimestampNs_notnull "select minute_floor(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_minute_floor_DateTime_DateTime "select minute_floor(kdtm, kdtm) from fn_test order by kdtm, kdtm" qt_sql_minute_floor_DateTime_DateTime_notnull "select minute_floor(kdtm, kdtm) from fn_test_not_nullable order by kdtm, kdtm" qt_sql_minute_floor_DateTime_Integer "select minute_floor(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_minute_floor_DateTime_Integer_notnull "select minute_floor(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_minute_floor_DateTimeV2_DateTimeV2 "select minute_floor(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_minute_floor_TimestampNs_TimestampNs "select minute_floor(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_minute_floor_DateTimeV2_DateTimeV2_notnull "select minute_floor(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_minute_floor_TimestampNs_TimestampNs_notnull "select minute_floor(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_minute_floor_DateTimeV2_Integer "select minute_floor(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_minute_floor_TimestampNs_Integer "select minute_floor(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_minute_floor_DateTimeV2_Integer_notnull "select minute_floor(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_minute_floor_TimestampNs_Integer_notnull "select minute_floor(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_minute_floor_DateTime_Integer_DateTime "select minute_floor(kdtm, kint, kdtm) from fn_test order by kdtm, kint, kdtm" qt_sql_minute_floor_DateTime_Integer_DateTime_notnull "select minute_floor(kdtm, kint, kdtm) from fn_test_not_nullable order by kdtm, kint, kdtm" qt_sql_minute_floor_DateTimeV2_Integer_DateTimeV2 "select minute_floor(kdtmv2s1, kint, kdtmv2s1) from fn_test order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_minute_floor_TimestampNs_Integer_TimestampNs "select minute_floor(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_minute_floor_DateTimeV2_Integer_DateTimeV2_notnull "select minute_floor(kdtmv2s1, kint, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_minute_floor_TimestampNs_Integer_TimestampNs_notnull "select minute_floor(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_minutes_add_DateTime_Integer "select minutes_add(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_minutes_add_DateTime_Integer_notnull "select minutes_add(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_minutes_add_DateTimeV2_Integer "select minutes_add(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_minutes_add_TimestampNs_Integer "select minutes_add(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_minutes_add_DateTimeV2_Integer_notnull "select minutes_add(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_minutes_add_TimestampNs_Integer_notnull "select minutes_add(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_minutes_add_Date_Integer "select minutes_add(kdt, kint) from fn_test order by kdt, kint" qt_sql_minutes_add_Date_Integer_notnull "select minutes_add(kdt, kint) from fn_test_not_nullable order by kdt, kint" qt_sql_minutes_add_DateV2_Integer "select minutes_add(kdtv2, kint) from fn_test order by kdtv2, kint" @@ -98,11 +118,17 @@ suite("nereids_scalar_fn_M") { qt_sql_minutes_diff_DateTime_DateTime "select minutes_diff(kdtm, kdtm) from fn_test order by kdtm, kdtm" qt_sql_minutes_diff_DateTime_DateTime_notnull "select minutes_diff(kdtm, kdtm) from fn_test_not_nullable order by kdtm, kdtm" qt_sql_minutes_diff_DateTimeV2_DateTimeV2 "select minutes_diff(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_minutes_diff_TimestampNs_TimestampNs "select minutes_diff(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_minutes_diff_DateTimeV2_DateTimeV2_notnull "select minutes_diff(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_minutes_diff_TimestampNs_TimestampNs_notnull "select minutes_diff(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_minutes_diff_DateV2_DateTimeV2 "select minutes_diff(kdtv2, kdtmv2s1) from fn_test order by kdtv2, kdtmv2s1" + qt_sql_minutes_diff_DateV2_TimestampNs "select minutes_diff(kdtv2, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by kdtv2, cast(kdtmv2s1 as timestamp_ns)" qt_sql_minutes_diff_DateV2_DateTimeV2_notnull "select minutes_diff(kdtv2, kdtmv2s1) from fn_test_not_nullable order by kdtv2, kdtmv2s1" + qt_sql_minutes_diff_DateV2_TimestampNs_notnull "select minutes_diff(kdtv2, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by kdtv2, cast(kdtmv2s1 as timestamp_ns)" qt_sql_minutes_diff_DateTimeV2_DateV2 "select minutes_diff(kdtmv2s1, kdtv2) from fn_test order by kdtmv2s1, kdtv2" + qt_sql_minutes_diff_TimestampNs_DateV2 "select minutes_diff(cast(kdtmv2s1 as timestamp_ns), kdtv2) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kdtv2" qt_sql_minutes_diff_DateTimeV2_DateV2_notnull "select minutes_diff(kdtmv2s1, kdtv2) from fn_test_not_nullable order by kdtmv2s1, kdtv2" + qt_sql_minutes_diff_TimestampNs_DateV2_notnull "select minutes_diff(cast(kdtmv2s1 as timestamp_ns), kdtv2) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kdtv2" qt_sql_minutes_diff_DateV2_DateV2 "select minutes_diff(kdtv2, kdtv2) from fn_test order by kdtv2, kdtv2" qt_sql_minutes_diff_DateV2_DateV2_notnull "select minutes_diff(kdtv2, kdtv2) from fn_test_not_nullable order by kdtv2, kdtv2" qt_sql_minutes_diff_DateV2_DateTime "select minutes_diff(kdtv2, kdtm) from fn_test order by kdtv2, kdtm" @@ -110,13 +136,19 @@ suite("nereids_scalar_fn_M") { qt_sql_minutes_diff_DateTime_DateV2 "select minutes_diff(kdtm, kdtv2) from fn_test order by kdtm, kdtv2" qt_sql_minutes_diff_DateTime_DateV2_notnull "select minutes_diff(kdtm, kdtv2) from fn_test_not_nullable order by kdtm, kdtv2" qt_sql_minutes_diff_DateTimeV2_DateTime "select minutes_diff(kdtmv2s1, kdtm) from fn_test order by kdtmv2s1, kdtm" + qt_sql_minutes_diff_TimestampNs_DateTime "select minutes_diff(cast(kdtmv2s1 as timestamp_ns), kdtm) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kdtm" qt_sql_minutes_diff_DateTimeV2_DateTime_notnull "select minutes_diff(kdtmv2s1, kdtm) from fn_test_not_nullable order by kdtmv2s1, kdtm" + qt_sql_minutes_diff_TimestampNs_DateTime_notnull "select minutes_diff(cast(kdtmv2s1 as timestamp_ns), kdtm) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kdtm" qt_sql_minutes_diff_DateTime_DateTimeV2 "select minutes_diff(kdtm, kdtmv2s1) from fn_test order by kdtm, kdtmv2s1" + qt_sql_minutes_diff_DateTime_TimestampNs "select minutes_diff(kdtm, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by kdtm, cast(kdtmv2s1 as timestamp_ns)" qt_sql_minutes_diff_DateTime_DateTimeV2_notnull "select minutes_diff(kdtm, kdtmv2s1) from fn_test_not_nullable order by kdtm, kdtmv2s1" + qt_sql_minutes_diff_DateTime_TimestampNs_notnull "select minutes_diff(kdtm, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by kdtm, cast(kdtmv2s1 as timestamp_ns)" qt_sql_minutes_sub_DateTime_Integer "select minutes_sub(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_minutes_sub_DateTime_Integer_notnull "select minutes_sub(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_minutes_sub_DateTimeV2_Integer "select minutes_sub(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_minutes_sub_TimestampNs_Integer "select minutes_sub(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_minutes_sub_DateTimeV2_Integer_notnull "select minutes_sub(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_minutes_sub_TimestampNs_Integer_notnull "select minutes_sub(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_minutes_sub_Date_Integer "select minutes_sub(kdt, kint) from fn_test order by kdt, kint" qt_sql_minutes_sub_Date_Integer_notnull "select minutes_sub(kdt, kint) from fn_test_not_nullable order by kdt, kint" qt_sql_minutes_sub_DateV2_Integer "select minutes_sub(kdtv2, kint) from fn_test order by kdtv2, kint" @@ -132,14 +164,18 @@ suite("nereids_scalar_fn_M") { qt_sql_month_DateTime "select month(kdtm) from fn_test order by kdtm" qt_sql_month_DateTime_notnull "select month(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_month_DateTimeV2 "select month(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_month_TimestampNs "select month(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_month_DateTimeV2_notnull "select month(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_month_TimestampNs_notnull "select month(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_month_DateV2 "select month(kdtv2) from fn_test order by kdtv2" qt_sql_month_DateV2_notnull "select month(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_month_nullable_string_literal "select month(cast('2021-12-31 12:23:34' as datetimev2(0))), month(nullable('2021-12-31 12:23:34')), month(cast('0000-01-01 00:00:00' as datetimev2(0))), month(nullable('0000-01-01 00:00:00')), month(cast('0000-01-02 00:00:00' as datetimev2(0))), month(nullable('0000-01-02 00:00:00')), month(null)" qt_sql_month_ceil_DateTime "select month_ceil(kdtm) from fn_test order by kdtm" qt_sql_month_ceil_DateTime_notnull "select month_ceil(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_month_ceil_DateTimeV2 "select month_ceil(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_month_ceil_TimestampNs "select month_ceil(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_month_ceil_DateTimeV2_notnull "select month_ceil(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_month_ceil_TimestampNs_notnull "select month_ceil(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_month_ceil_DateV2 "select month_ceil(kdtv2) from fn_test order by kdtv2" qt_sql_month_ceil_DateV2_notnull "select month_ceil(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_month_ceil_DateTime_DateTime "select month_ceil(kdtm, kdtm) from fn_test order by kdtm, kdtm" @@ -147,9 +183,13 @@ suite("nereids_scalar_fn_M") { qt_sql_month_ceil_DateTime_Integer "select month_ceil(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_month_ceil_DateTime_Integer_notnull "select month_ceil(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_month_ceil_DateTimeV2_DateTimeV2 "select month_ceil(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_month_ceil_TimestampNs_TimestampNs "select month_ceil(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_month_ceil_DateTimeV2_DateTimeV2_notnull "select month_ceil(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_month_ceil_TimestampNs_TimestampNs_notnull "select month_ceil(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_month_ceil_DateTimeV2_Integer "select month_ceil(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_month_ceil_TimestampNs_Integer "select month_ceil(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_month_ceil_DateTimeV2_Integer_notnull "select month_ceil(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_month_ceil_TimestampNs_Integer_notnull "select month_ceil(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_month_ceil_DateV2_DateV2 "select month_ceil(kdtv2, kdtv2) from fn_test order by kdtv2, kdtv2" qt_sql_month_ceil_DateV2_DateV2_notnull "select month_ceil(kdtv2, kdtv2) from fn_test_not_nullable order by kdtv2, kdtv2" qt_sql_month_ceil_DateV2_Integer "select month_ceil(kdtv2, kint) from fn_test order by kdtv2, kint" @@ -157,13 +197,17 @@ suite("nereids_scalar_fn_M") { qt_sql_month_ceil_DateTime_Integer_DateTime "select month_ceil(kdtm, kint, kdtm) from fn_test order by kdtm, kint, kdtm" qt_sql_month_ceil_DateTime_Integer_DateTime_notnull "select month_ceil(kdtm, kint, kdtm) from fn_test_not_nullable order by kdtm, kint, kdtm" qt_sql_month_ceil_DateTimeV2_Integer_DateTimeV2 "select month_ceil(kdtmv2s1, kint, kdtmv2s1) from fn_test order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_month_ceil_TimestampNs_Integer_TimestampNs "select month_ceil(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_month_ceil_DateTimeV2_Integer_DateTimeV2_notnull "select month_ceil(kdtmv2s1, kint, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_month_ceil_TimestampNs_Integer_TimestampNs_notnull "select month_ceil(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_month_ceil_DateV2_Integer_DateV2 "select month_ceil(kdtv2, kint, kdtv2) from fn_test order by kdtv2, kint, kdtv2" qt_sql_month_ceil_DateV2_Integer_DateV2_notnull "select month_ceil(kdtv2, kint, kdtv2) from fn_test_not_nullable order by kdtv2, kint, kdtv2" qt_sql_month_floor_DateTime "select month_floor(kdtm) from fn_test order by kdtm" qt_sql_month_floor_DateTime_notnull "select month_floor(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_month_floor_DateTimeV2 "select month_floor(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_month_floor_TimestampNs "select month_floor(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_month_floor_DateTimeV2_notnull "select month_floor(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_month_floor_TimestampNs_notnull "select month_floor(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_month_floor_DateV2 "select month_floor(kdtv2) from fn_test order by kdtv2" qt_sql_month_floor_DateV2_notnull "select month_floor(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_month_floor_DateTime_DateTime "select month_floor(kdtm, kdtm) from fn_test order by kdtm, kdtm" @@ -171,9 +215,13 @@ suite("nereids_scalar_fn_M") { qt_sql_month_floor_DateTime_Integer "select month_floor(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_month_floor_DateTime_Integer_notnull "select month_floor(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_month_floor_DateTimeV2_DateTimeV2 "select month_floor(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_month_floor_TimestampNs_TimestampNs "select month_floor(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_month_floor_DateTimeV2_DateTimeV2_notnull "select month_floor(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_month_floor_TimestampNs_TimestampNs_notnull "select month_floor(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_month_floor_DateTimeV2_Integer "select month_floor(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_month_floor_TimestampNs_Integer "select month_floor(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_month_floor_DateTimeV2_Integer_notnull "select month_floor(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_month_floor_TimestampNs_Integer_notnull "select month_floor(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_month_floor_DateV2_DateV2 "select month_floor(kdtv2, kdtv2) from fn_test order by kdtv2, kdtv2" qt_sql_month_floor_DateV2_DateV2_notnull "select month_floor(kdtv2, kdtv2) from fn_test_not_nullable order by kdtv2, kdtv2" qt_sql_month_floor_DateV2_Integer "select month_floor(kdtv2, kint) from fn_test order by kdtv2, kint" @@ -181,19 +229,25 @@ suite("nereids_scalar_fn_M") { qt_sql_month_floor_DateTime_Integer_DateTime "select month_floor(kdtm, kint, kdtm) from fn_test order by kdtm, kint, kdtm" qt_sql_month_floor_DateTime_Integer_DateTime_notnull "select month_floor(kdtm, kint, kdtm) from fn_test_not_nullable order by kdtm, kint, kdtm" qt_sql_month_floor_DateTimeV2_Integer_DateTimeV2 "select month_floor(kdtmv2s1, kint, kdtmv2s1) from fn_test order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_month_floor_TimestampNs_Integer_TimestampNs "select month_floor(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_month_floor_DateTimeV2_Integer_DateTimeV2_notnull "select month_floor(kdtmv2s1, kint, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_month_floor_TimestampNs_Integer_TimestampNs_notnull "select month_floor(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_month_floor_DateV2_Integer_DateV2 "select month_floor(kdtv2, kint, kdtv2) from fn_test order by kdtv2, kint, kdtv2" qt_sql_month_floor_DateV2_Integer_DateV2_notnull "select month_floor(kdtv2, kint, kdtv2) from fn_test_not_nullable order by kdtv2, kint, kdtv2" qt_sql_monthname_DateTime "select monthname(kdtm) from fn_test order by kdtm" qt_sql_monthname_DateTime_notnull "select monthname(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_monthname_DateTimeV2 "select monthname(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_monthname_TimestampNs "select monthname(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_monthname_DateTimeV2_notnull "select monthname(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_monthname_TimestampNs_notnull "select monthname(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_monthname_DateV2 "select monthname(kdtv2) from fn_test order by kdtv2" qt_sql_monthname_DateV2_notnull "select monthname(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_months_add_DateTime_Integer "select months_add(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_months_add_DateTime_Integer_notnull "select months_add(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_months_add_DateTimeV2_Integer "select months_add(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_months_add_TimestampNs_Integer "select months_add(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_months_add_DateTimeV2_Integer_notnull "select months_add(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_months_add_TimestampNs_Integer_notnull "select months_add(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_months_add_Date_Integer "select months_add(kdt, kint) from fn_test order by kdt, kint" qt_sql_months_add_Date_Integer_notnull "select months_add(kdt, kint) from fn_test_not_nullable order by kdt, kint" qt_sql_months_add_DateV2_Integer "select months_add(kdtv2, kint) from fn_test order by kdtv2, kint" @@ -201,11 +255,17 @@ suite("nereids_scalar_fn_M") { qt_sql_months_diff_DateTime_DateTime "select months_diff(kdtm, kdtm) from fn_test order by kdtm, kdtm" qt_sql_months_diff_DateTime_DateTime_notnull "select months_diff(kdtm, kdtm) from fn_test_not_nullable order by kdtm, kdtm" qt_sql_months_diff_DateTimeV2_DateTimeV2 "select months_diff(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_months_diff_TimestampNs_TimestampNs "select months_diff(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_months_diff_DateTimeV2_DateTimeV2_notnull "select months_diff(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_months_diff_TimestampNs_TimestampNs_notnull "select months_diff(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_months_diff_DateV2_DateTimeV2 "select months_diff(kdtv2, kdtmv2s1) from fn_test order by kdtv2, kdtmv2s1" + qt_sql_months_diff_DateV2_TimestampNs "select months_diff(kdtv2, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by kdtv2, cast(kdtmv2s1 as timestamp_ns)" qt_sql_months_diff_DateV2_DateTimeV2_notnull "select months_diff(kdtv2, kdtmv2s1) from fn_test_not_nullable order by kdtv2, kdtmv2s1" + qt_sql_months_diff_DateV2_TimestampNs_notnull "select months_diff(kdtv2, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by kdtv2, cast(kdtmv2s1 as timestamp_ns)" qt_sql_months_diff_DateTimeV2_DateV2 "select months_diff(kdtmv2s1, kdtv2) from fn_test order by kdtmv2s1, kdtv2" + qt_sql_months_diff_TimestampNs_DateV2 "select months_diff(cast(kdtmv2s1 as timestamp_ns), kdtv2) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kdtv2" qt_sql_months_diff_DateTimeV2_DateV2_notnull "select months_diff(kdtmv2s1, kdtv2) from fn_test_not_nullable order by kdtmv2s1, kdtv2" + qt_sql_months_diff_TimestampNs_DateV2_notnull "select months_diff(cast(kdtmv2s1 as timestamp_ns), kdtv2) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kdtv2" qt_sql_months_diff_DateV2_DateV2 "select months_diff(kdtv2, kdtv2) from fn_test order by kdtv2, kdtv2" qt_sql_months_diff_DateV2_DateV2_notnull "select months_diff(kdtv2, kdtv2) from fn_test_not_nullable order by kdtv2, kdtv2" qt_sql_months_diff_DateV2_DateTime "select months_diff(kdtv2, kdtm) from fn_test order by kdtv2, kdtm" @@ -213,13 +273,19 @@ suite("nereids_scalar_fn_M") { qt_sql_months_diff_DateTime_DateV2 "select months_diff(kdtm, kdtv2) from fn_test order by kdtm, kdtv2" qt_sql_months_diff_DateTime_DateV2_notnull "select months_diff(kdtm, kdtv2) from fn_test_not_nullable order by kdtm, kdtv2" qt_sql_months_diff_DateTimeV2_DateTime "select months_diff(kdtmv2s1, kdtm) from fn_test order by kdtmv2s1, kdtm" + qt_sql_months_diff_TimestampNs_DateTime "select months_diff(cast(kdtmv2s1 as timestamp_ns), kdtm) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kdtm" qt_sql_months_diff_DateTimeV2_DateTime_notnull "select months_diff(kdtmv2s1, kdtm) from fn_test_not_nullable order by kdtmv2s1, kdtm" + qt_sql_months_diff_TimestampNs_DateTime_notnull "select months_diff(cast(kdtmv2s1 as timestamp_ns), kdtm) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kdtm" qt_sql_months_diff_DateTime_DateTimeV2 "select months_diff(kdtm, kdtmv2s1) from fn_test order by kdtm, kdtmv2s1" + qt_sql_months_diff_DateTime_TimestampNs "select months_diff(kdtm, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by kdtm, cast(kdtmv2s1 as timestamp_ns)" qt_sql_months_diff_DateTime_DateTimeV2_notnull "select months_diff(kdtm, kdtmv2s1) from fn_test_not_nullable order by kdtm, kdtmv2s1" + qt_sql_months_diff_DateTime_TimestampNs_notnull "select months_diff(kdtm, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by kdtm, cast(kdtmv2s1 as timestamp_ns)" qt_sql_months_sub_DateTime_Integer "select months_sub(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_months_sub_DateTime_Integer_notnull "select months_sub(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_months_sub_DateTimeV2_Integer "select months_sub(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_months_sub_TimestampNs_Integer "select months_sub(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_months_sub_DateTimeV2_Integer_notnull "select months_sub(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_months_sub_TimestampNs_Integer_notnull "select months_sub(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_months_sub_Date_Integer "select months_sub(kdt, kint) from fn_test order by kdt, kint" qt_sql_months_sub_Date_Integer_notnull "select months_sub(kdt, kint) from fn_test_not_nullable order by kdt, kint" qt_sql_months_sub_DateV2_Integer "select months_sub(kdtv2, kint) from fn_test order by kdtv2, kint" diff --git a/regression-test/suites/nereids_function_p0/scalar_function/N.groovy b/regression-test/suites/nereids_function_p0/scalar_function/N.groovy index c99372058ecc1d..6e9001066f228f 100644 --- a/regression-test/suites/nereids_function_p0/scalar_function/N.groovy +++ b/regression-test/suites/nereids_function_p0/scalar_function/N.groovy @@ -58,7 +58,9 @@ suite("nereids_scalar_fn_N") { qt_sql_nullif_Date_Date "select nullif(kdt, kdt) from fn_test order by kdt, kdt" qt_sql_nullif_Date_Date_notnull "select nullif(kdt, kdt) from fn_test_not_nullable order by kdt, kdt" qt_sql_nullif_DateTimeV2_DateTimeV2 "select nullif(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_nullif_TimestampNs_TimestampNs "select nullif(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_nullif_DateTimeV2_DateTimeV2_notnull "select nullif(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_nullif_TimestampNs_TimestampNs_notnull "select nullif(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_nullif_DateV2_DateV2 "select nullif(kdtv2, kdtv2) from fn_test order by kdtv2, kdtv2" qt_sql_nullif_DateV2_DateV2_notnull "select nullif(kdtv2, kdtv2) from fn_test_not_nullable order by kdtv2, kdtv2" qt_sql_nullif_DecimalV2_DecimalV2 "select nullif(kdcmls1, kdcmls1) from fn_test order by kdcmls1, kdcmls1" @@ -92,7 +94,9 @@ suite("nereids_scalar_fn_N") { qt_sql_nvl_DateTime_Date "select nvl(kdtm, kdt) from fn_test order by kdtm, kdt" qt_sql_nvl_DateTime_Date_notnull "select nvl(kdtm, kdt) from fn_test_not_nullable order by kdtm, kdt" qt_sql_nvl_DateTimeV2_DateTimeV2 "select nvl(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_nvl_TimestampNs_TimestampNs "select nvl(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_nvl_DateTimeV2_DateTimeV2_notnull "select nvl(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_nvl_TimestampNs_TimestampNs_notnull "select nvl(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_nvl_DateV2_DateV2 "select nvl(kdtv2, kdtv2) from fn_test order by kdtv2, kdtv2" qt_sql_nvl_DateV2_DateV2_notnull "select nvl(kdtv2, kdtv2) from fn_test_not_nullable order by kdtv2, kdtv2" qt_sql_nvl_DecimalV2_DecimalV2 "select nvl(kdcmls1, kdcmls1) from fn_test order by kdcmls1, kdcmls1" diff --git a/regression-test/suites/nereids_function_p0/scalar_function/Q.groovy b/regression-test/suites/nereids_function_p0/scalar_function/Q.groovy index 1a1f0ac502f12d..88699878e47d29 100644 --- a/regression-test/suites/nereids_function_p0/scalar_function/Q.groovy +++ b/regression-test/suites/nereids_function_p0/scalar_function/Q.groovy @@ -22,7 +22,9 @@ suite("nereids_scalar_fn_Q") { qt_sql_quarter_DateTime "select quarter(kdtm) from fn_test order by kdtm" qt_sql_quarter_DateTime_notnull "select quarter(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_quarter_DateTimeV2 "select quarter(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_quarter_TimestampNs "select quarter(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_quarter_DateTimeV2_notnull "select quarter(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_quarter_TimestampNs_notnull "select quarter(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_quarter_DateV2 "select quarter(kdtv2) from fn_test order by kdtv2" qt_sql_quarter_DateV2_notnull "select quarter(kdtv2) from fn_test_not_nullable order by kdtv2" } \ No newline at end of file diff --git a/regression-test/suites/nereids_function_p0/scalar_function/S.groovy b/regression-test/suites/nereids_function_p0/scalar_function/S.groovy index cce6d4ac83e7b1..4c5c8bac1c0cdd 100644 --- a/regression-test/suites/nereids_function_p0/scalar_function/S.groovy +++ b/regression-test/suites/nereids_function_p0/scalar_function/S.groovy @@ -22,7 +22,9 @@ suite("nereids_scalar_fn_S") { qt_sql_second_DateTime "select second(kdtm) from fn_test order by kdtm" qt_sql_second_DateTime_notnull "select second(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_second_DateTimeV2 "select second(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_second_TimestampNs "select second(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_second_DateTimeV2_notnull "select second(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_second_TimestampNs_notnull "select second(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_second_DateV2 "select second(kdtv2) from fn_test order by kdtv2" qt_sql_second_DateV2_notnull "select second(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_second_time_like_string_literal "select second('01:02:03')" @@ -31,39 +33,57 @@ suite("nereids_scalar_fn_S") { qt_sql_second_ceil_DateTime "select second_ceil(kdtm) from fn_test order by kdtm" qt_sql_second_ceil_DateTime_notnull "select second_ceil(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_second_ceil_DateTimeV2 "select second_ceil(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_second_ceil_TimestampNs "select second_ceil(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_second_ceil_DateTimeV2_notnull "select second_ceil(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_second_ceil_TimestampNs_notnull "select second_ceil(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_second_ceil_DateTime_DateTime "select second_ceil(kdtm, kdtm) from fn_test order by kdtm, kdtm" qt_sql_second_ceil_DateTime_DateTime_notnull "select second_ceil(kdtm, kdtm) from fn_test_not_nullable order by kdtm, kdtm" qt_sql_second_ceil_DateTime_Integer "select second_ceil(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_second_ceil_DateTime_Integer_notnull "select second_ceil(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_second_ceil_DateTimeV2_DateTimeV2 "select second_ceil(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_second_ceil_TimestampNs_TimestampNs "select second_ceil(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_second_ceil_DateTimeV2_DateTimeV2_notnull "select second_ceil(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_second_ceil_TimestampNs_TimestampNs_notnull "select second_ceil(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_second_ceil_DateTimeV2_Integer "select second_ceil(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_second_ceil_TimestampNs_Integer "select second_ceil(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_second_ceil_DateTimeV2_Integer_notnull "select second_ceil(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_second_ceil_TimestampNs_Integer_notnull "select second_ceil(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_second_ceil_DateTime_Integer_DateTime "select second_ceil(kdtm, kint, kdtm) from fn_test order by kdtm, kint, kdtm" qt_sql_second_ceil_DateTime_Integer_DateTime_notnull "select second_ceil(kdtm, kint, kdtm) from fn_test_not_nullable order by kdtm, kint, kdtm" qt_sql_second_ceil_DateTimeV2_Integer_DateTimeV2 "select second_ceil(kdtmv2s1, kint, kdtmv2s1) from fn_test order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_second_ceil_TimestampNs_Integer_TimestampNs "select second_ceil(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_second_ceil_DateTimeV2_Integer_DateTimeV2_notnull "select second_ceil(kdtmv2s1, kint, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_second_ceil_TimestampNs_Integer_TimestampNs_notnull "select second_ceil(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_second_floor_DateTime "select second_floor(kdtm) from fn_test order by kdtm" qt_sql_second_floor_DateTime_notnull "select second_floor(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_second_floor_DateTimeV2 "select second_floor(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_second_floor_TimestampNs "select second_floor(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_second_floor_DateTimeV2_notnull "select second_floor(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_second_floor_TimestampNs_notnull "select second_floor(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_second_floor_DateTime_DateTime "select second_floor(kdtm, kdtm) from fn_test order by kdtm, kdtm" qt_sql_second_floor_DateTime_DateTime_notnull "select second_floor(kdtm, kdtm) from fn_test_not_nullable order by kdtm, kdtm" qt_sql_second_floor_DateTime_Integer "select second_floor(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_second_floor_DateTime_Integer_notnull "select second_floor(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_second_floor_DateTimeV2_DateTimeV2 "select second_floor(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_second_floor_TimestampNs_TimestampNs "select second_floor(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_second_floor_DateTimeV2_DateTimeV2_notnull "select second_floor(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_second_floor_TimestampNs_TimestampNs_notnull "select second_floor(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_second_floor_DateTimeV2_Integer "select second_floor(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_second_floor_TimestampNs_Integer "select second_floor(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_second_floor_DateTimeV2_Integer_notnull "select second_floor(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_second_floor_TimestampNs_Integer_notnull "select second_floor(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_second_floor_DateTime_Integer_DateTime "select second_floor(kdtm, kint, kdtm) from fn_test order by kdtm, kint, kdtm" qt_sql_second_floor_DateTime_Integer_DateTime_notnull "select second_floor(kdtm, kint, kdtm) from fn_test_not_nullable order by kdtm, kint, kdtm" qt_sql_second_floor_DateTimeV2_Integer_DateTimeV2 "select second_floor(kdtmv2s1, kint, kdtmv2s1) from fn_test order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_second_floor_TimestampNs_Integer_TimestampNs "select second_floor(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_second_floor_DateTimeV2_Integer_DateTimeV2_notnull "select second_floor(kdtmv2s1, kint, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_second_floor_TimestampNs_Integer_TimestampNs_notnull "select second_floor(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_seconds_add_DateTime_Integer "select seconds_add(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_seconds_add_DateTime_Integer_notnull "select seconds_add(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_seconds_add_DateTimeV2_Integer "select seconds_add(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_seconds_add_TimestampNs_Integer "select seconds_add(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_seconds_add_DateTimeV2_Integer_notnull "select seconds_add(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_seconds_add_TimestampNs_Integer_notnull "select seconds_add(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_seconds_add_Date_Integer "select seconds_add(kdt, kint) from fn_test order by kdt, kint" qt_sql_seconds_add_Date_Integer_notnull "select seconds_add(kdt, kint) from fn_test_not_nullable order by kdt, kint" qt_sql_seconds_add_DateV2_Integer "select seconds_add(kdtv2, kint) from fn_test order by kdtv2, kint" @@ -71,11 +91,17 @@ suite("nereids_scalar_fn_S") { qt_sql_seconds_diff_DateTime_DateTime "select seconds_diff(kdtm, kdtm) from fn_test order by kdtm, kdtm" qt_sql_seconds_diff_DateTime_DateTime_notnull "select seconds_diff(kdtm, kdtm) from fn_test_not_nullable order by kdtm, kdtm" qt_sql_seconds_diff_DateTimeV2_DateTimeV2 "select seconds_diff(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_seconds_diff_TimestampNs_TimestampNs "select seconds_diff(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_seconds_diff_DateTimeV2_DateTimeV2_notnull "select seconds_diff(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_seconds_diff_TimestampNs_TimestampNs_notnull "select seconds_diff(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_seconds_diff_DateV2_DateTimeV2 "select seconds_diff(kdtv2, kdtmv2s1) from fn_test order by kdtv2, kdtmv2s1" + qt_sql_seconds_diff_DateV2_TimestampNs "select seconds_diff(kdtv2, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by kdtv2, cast(kdtmv2s1 as timestamp_ns)" qt_sql_seconds_diff_DateV2_DateTimeV2_notnull "select seconds_diff(kdtv2, kdtmv2s1) from fn_test_not_nullable order by kdtv2, kdtmv2s1" + qt_sql_seconds_diff_DateV2_TimestampNs_notnull "select seconds_diff(kdtv2, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by kdtv2, cast(kdtmv2s1 as timestamp_ns)" qt_sql_seconds_diff_DateTimeV2_DateV2 "select seconds_diff(kdtmv2s1, kdtv2) from fn_test order by kdtmv2s1, kdtv2" + qt_sql_seconds_diff_TimestampNs_DateV2 "select seconds_diff(cast(kdtmv2s1 as timestamp_ns), kdtv2) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kdtv2" qt_sql_seconds_diff_DateTimeV2_DateV2_notnull "select seconds_diff(kdtmv2s1, kdtv2) from fn_test_not_nullable order by kdtmv2s1, kdtv2" + qt_sql_seconds_diff_TimestampNs_DateV2_notnull "select seconds_diff(cast(kdtmv2s1 as timestamp_ns), kdtv2) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kdtv2" qt_sql_seconds_diff_DateV2_DateV2 "select seconds_diff(kdtv2, kdtv2) from fn_test order by kdtv2, kdtv2" qt_sql_seconds_diff_DateV2_DateV2_notnull "select seconds_diff(kdtv2, kdtv2) from fn_test_not_nullable order by kdtv2, kdtv2" qt_sql_seconds_diff_DateV2_DateTime "select seconds_diff(kdtv2, kdtm) from fn_test order by kdtv2, kdtm" @@ -83,9 +109,13 @@ suite("nereids_scalar_fn_S") { qt_sql_seconds_diff_DateTime_DateV2 "select seconds_diff(kdtm, kdtv2) from fn_test order by kdtm, kdtv2" qt_sql_seconds_diff_DateTime_DateV2_notnull "select seconds_diff(kdtm, kdtv2) from fn_test_not_nullable order by kdtm, kdtv2" qt_sql_seconds_diff_DateTimeV2_DateTime "select seconds_diff(kdtmv2s1, kdtm) from fn_test order by kdtmv2s1, kdtm" + qt_sql_seconds_diff_TimestampNs_DateTime "select seconds_diff(cast(kdtmv2s1 as timestamp_ns), kdtm) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kdtm" qt_sql_seconds_diff_DateTimeV2_DateTime_notnull "select seconds_diff(kdtmv2s1, kdtm) from fn_test_not_nullable order by kdtmv2s1, kdtm" + qt_sql_seconds_diff_TimestampNs_DateTime_notnull "select seconds_diff(cast(kdtmv2s1 as timestamp_ns), kdtm) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kdtm" qt_sql_seconds_diff_DateTime_DateTimeV2 "select seconds_diff(kdtm, kdtmv2s1) from fn_test order by kdtm, kdtmv2s1" + qt_sql_seconds_diff_DateTime_TimestampNs "select seconds_diff(kdtm, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by kdtm, cast(kdtmv2s1 as timestamp_ns)" qt_sql_seconds_diff_DateTime_DateTimeV2_notnull "select seconds_diff(kdtm, kdtmv2s1) from fn_test_not_nullable order by kdtm, kdtmv2s1" + qt_sql_seconds_diff_DateTime_TimestampNs_notnull "select seconds_diff(kdtm, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by kdtm, cast(kdtmv2s1 as timestamp_ns)" qt_sql_sign_Double "select sign(kdbl) from fn_test order by kdbl" qt_sql_sign_Double_notnull "select sign(kdbl) from fn_test_not_nullable order by kdbl" qt_sql_signbit_Double "select signbit(kdbl) from fn_test order by kdbl" diff --git a/regression-test/suites/nereids_function_p0/scalar_function/T.groovy b/regression-test/suites/nereids_function_p0/scalar_function/T.groovy index 86db66358c41a9..02301605bb916d 100644 --- a/regression-test/suites/nereids_function_p0/scalar_function/T.groovy +++ b/regression-test/suites/nereids_function_p0/scalar_function/T.groovy @@ -26,19 +26,29 @@ suite("nereids_scalar_fn_T") { qt_sql_timediff_DateTime_DateTime "select timediff(kdtm, kdtm) from fn_test order by kdtm, kdtm" qt_sql_timediff_DateTime_DateTime_notnull "select timediff(kdtm, kdtm) from fn_test_not_nullable order by kdtm, kdtm" qt_sql_timediff_DateTimeV2_DateTimeV2 "select timediff(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_timediff_TimestampNs_TimestampNs "select timediff(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_timediff_DateTimeV2_DateTimeV2_notnull "select timediff(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_timediff_TimestampNs_TimestampNs_notnull "select timediff(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_timediff_DateTimeV2_DateV2 "select timediff(kdtmv2s1, kdtv2) from fn_test order by kdtmv2s1, kdtv2" + qt_sql_timediff_TimestampNs_DateV2 "select timediff(cast(kdtmv2s1 as timestamp_ns), kdtv2) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kdtv2" qt_sql_timediff_DateTimeV2_DateV2_notnull "select timediff(kdtmv2s1, kdtv2) from fn_test_not_nullable order by kdtmv2s1, kdtv2" + qt_sql_timediff_TimestampNs_DateV2_notnull "select timediff(cast(kdtmv2s1 as timestamp_ns), kdtv2) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kdtv2" qt_sql_timediff_DateV2_DateTimeV2 "select timediff(kdtv2, kdtmv2s1) from fn_test order by kdtv2, kdtmv2s1" + qt_sql_timediff_DateV2_TimestampNs "select timediff(kdtv2, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by kdtv2, cast(kdtmv2s1 as timestamp_ns)" qt_sql_timediff_DateV2_DateTimeV2_notnull "select timediff(kdtv2, kdtmv2s1) from fn_test_not_nullable order by kdtv2, kdtmv2s1" + qt_sql_timediff_DateV2_TimestampNs_notnull "select timediff(kdtv2, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by kdtv2, cast(kdtmv2s1 as timestamp_ns)" qt_sql_timediff_DateV2_DateV2 "select timediff(kdtv2, kdtv2) from fn_test order by kdtv2, kdtv2" qt_sql_timediff_DateV2_DateV2_notnull "select timediff(kdtv2, kdtv2) from fn_test_not_nullable order by kdtv2, kdtv2" qt_sql_timediff_DateTimeV2_DateTime "select timediff(kdtmv2s1, kdtm) from fn_test order by kdtmv2s1, kdtm" + qt_sql_timediff_TimestampNs_DateTime "select timediff(cast(kdtmv2s1 as timestamp_ns), kdtm) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kdtm" qt_sql_timediff_DateTimeV2_DateTime_notnull "select timediff(kdtmv2s1, kdtm) from fn_test_not_nullable order by kdtmv2s1, kdtm" + qt_sql_timediff_TimestampNs_DateTime_notnull "select timediff(cast(kdtmv2s1 as timestamp_ns), kdtm) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kdtm" qt_sql_timediff_DateV2_DateTime "select timediff(kdtv2, kdtm) from fn_test order by kdtv2, kdtm" qt_sql_timediff_DateV2_DateTime_notnull "select timediff(kdtv2, kdtm) from fn_test_not_nullable order by kdtv2, kdtm" qt_sql_timestamp_DateTimeV2 "select timestamp(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_timestamp_TimestampNs "select timestamp(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_timestamp_DateTimeV2_notnull "select timestamp(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_timestamp_TimestampNs_notnull "select timestamp(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_timestamp_DateTime "select timestamp(kdtm) from fn_test order by kdtm" qt_sql_timestamp_DateTime_notnull "select timestamp(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_timestamp_DateTime "select timestamp(kdtm) from fn_test order by kdtm" @@ -56,15 +66,21 @@ suite("nereids_scalar_fn_T") { qt_sql_to_date_DateTime "select to_date(kdtm) from fn_test order by kdtm" qt_sql_to_date_DateTime_notnull "select to_date(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_to_date_DateTimeV2 "select to_date(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_to_date_TimestampNs "select to_date(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_to_date_DateTimeV2_notnull "select to_date(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_to_date_TimestampNs_notnull "select to_date(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_to_datev2_DateTimeV2 "select to_datev2(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_to_datev2_TimestampNs "select to_datev2(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_to_datev2_DateTimeV2_notnull "select to_datev2(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_to_datev2_TimestampNs_notnull "select to_datev2(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_to_days_Date "select to_days(kdt) from fn_test order by kdt" qt_sql_to_days_Date_notnull "select to_days(kdt) from fn_test_not_nullable order by kdt" qt_sql_to_days_DateV2 "select to_days(kdtv2) from fn_test order by kdtv2" qt_sql_to_days_DateV2_notnull "select to_days(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_to_monday_DateTimeV2 "select to_monday(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_to_monday_TimestampNs "select to_monday(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_to_monday_DateTimeV2_notnull "select to_monday(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_to_monday_TimestampNs_notnull "select to_monday(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_to_monday_DateV2 "select to_monday(kdtv2) from fn_test order by kdtv2" qt_sql_to_monday_DateV2_notnull "select to_monday(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_to_monday_DateTime "select to_monday(kdtm) from fn_test order by kdtm" diff --git a/regression-test/suites/nereids_function_p0/scalar_function/U.groovy b/regression-test/suites/nereids_function_p0/scalar_function/U.groovy index f43bc4cb6eea97..736fa42681ba50 100644 --- a/regression-test/suites/nereids_function_p0/scalar_function/U.groovy +++ b/regression-test/suites/nereids_function_p0/scalar_function/U.groovy @@ -30,7 +30,9 @@ suite("nereids_scalar_fn_U") { qt_sql_unix_timestamp_Date "select unix_timestamp(kdt) from fn_test order by kdt" qt_sql_unix_timestamp_Date_notnull "select unix_timestamp(kdt) from fn_test_not_nullable order by kdt" qt_sql_unix_timestamp_DateTimeV2 "select unix_timestamp(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_unix_timestamp_TimestampNs "select unix_timestamp(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_unix_timestamp_DateTimeV2_notnull "select unix_timestamp(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_unix_timestamp_TimestampNs_notnull "select unix_timestamp(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_unix_timestamp_DateV2 "select unix_timestamp(kdtv2) from fn_test order by kdtv2" qt_sql_unix_timestamp_DateV2_notnull "select unix_timestamp(kdtv2) from fn_test_not_nullable order by kdtv2" test { diff --git a/regression-test/suites/nereids_function_p0/scalar_function/W.groovy b/regression-test/suites/nereids_function_p0/scalar_function/W.groovy index 015c4481f6b05e..25c1509c1a2e59 100644 --- a/regression-test/suites/nereids_function_p0/scalar_function/W.groovy +++ b/regression-test/suites/nereids_function_p0/scalar_function/W.groovy @@ -22,19 +22,25 @@ suite("nereids_scalar_fn_W") { qt_sql_week_DateTime "select week(kdtm) from fn_test order by kdtm" qt_sql_week_DateTime_notnull "select week(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_week_DateTimeV2 "select week(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_week_TimestampNs "select week(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_week_DateTimeV2_notnull "select week(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_week_TimestampNs_notnull "select week(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_week_DateV2 "select week(kdtv2) from fn_test order by kdtv2" qt_sql_week_DateV2_notnull "select week(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_week_DateTime_Integer "select week(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_week_DateTime_Integer_notnull "select week(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_week_DateTimeV2_Integer "select week(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_week_TimestampNs_Integer "select week(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_week_DateTimeV2_Integer_notnull "select week(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_week_TimestampNs_Integer_notnull "select week(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_week_DateV2_Integer "select week(kdtv2, kint) from fn_test order by kdtv2, kint" qt_sql_week_DateV2_Integer_notnull "select week(kdtv2, kint) from fn_test_not_nullable order by kdtv2, kint" qt_sql_week_ceil_DateTime "select week_ceil(kdtm) from fn_test order by kdtm" qt_sql_week_ceil_DateTime_notnull "select week_ceil(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_week_ceil_DateTimeV2 "select week_ceil(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_week_ceil_TimestampNs "select week_ceil(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_week_ceil_DateTimeV2_notnull "select week_ceil(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_week_ceil_TimestampNs_notnull "select week_ceil(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_week_ceil_DateV2 "select week_ceil(kdtv2) from fn_test order by kdtv2" qt_sql_week_ceil_DateV2_notnull "select week_ceil(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_week_ceil_DateTime_DateTime "select week_ceil(kdtm, kdtm) from fn_test order by kdtm, kdtm" @@ -42,9 +48,13 @@ suite("nereids_scalar_fn_W") { qt_sql_week_ceil_DateTime_Integer "select week_ceil(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_week_ceil_DateTime_Integer_notnull "select week_ceil(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_week_ceil_DateTimeV2_DateTimeV2 "select week_ceil(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_week_ceil_TimestampNs_TimestampNs "select week_ceil(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_week_ceil_DateTimeV2_DateTimeV2_notnull "select week_ceil(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_week_ceil_TimestampNs_TimestampNs_notnull "select week_ceil(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_week_ceil_DateTimeV2_Integer "select week_ceil(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_week_ceil_TimestampNs_Integer "select week_ceil(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_week_ceil_DateTimeV2_Integer_notnull "select week_ceil(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_week_ceil_TimestampNs_Integer_notnull "select week_ceil(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_week_ceil_DateV2_DateV2 "select week_ceil(kdtv2, kdtv2) from fn_test order by kdtv2, kdtv2" qt_sql_week_ceil_DateV2_DateV2_notnull "select week_ceil(kdtv2, kdtv2) from fn_test_not_nullable order by kdtv2, kdtv2" qt_sql_week_ceil_DateV2_Integer "select week_ceil(kdtv2, kint) from fn_test order by kdtv2, kint" @@ -52,13 +62,17 @@ suite("nereids_scalar_fn_W") { qt_sql_week_ceil_DateTime_Integer_DateTime "select week_ceil(kdtm, kint, kdtm) from fn_test order by kdtm, kint, kdtm" qt_sql_week_ceil_DateTime_Integer_DateTime_notnull "select week_ceil(kdtm, kint, kdtm) from fn_test_not_nullable order by kdtm, kint, kdtm" qt_sql_week_ceil_DateTimeV2_Integer_DateTimeV2 "select week_ceil(kdtmv2s1, kint, kdtmv2s1) from fn_test order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_week_ceil_TimestampNs_Integer_TimestampNs "select week_ceil(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_week_ceil_DateTimeV2_Integer_DateTimeV2_notnull "select week_ceil(kdtmv2s1, kint, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_week_ceil_TimestampNs_Integer_TimestampNs_notnull "select week_ceil(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_week_ceil_DateV2_Integer_DateV2 "select week_ceil(kdtv2, kint, kdtv2) from fn_test order by kdtv2, kint, kdtv2" qt_sql_week_ceil_DateV2_Integer_DateV2_notnull "select week_ceil(kdtv2, kint, kdtv2) from fn_test_not_nullable order by kdtv2, kint, kdtv2" qt_sql_week_floor_DateTime "select week_floor(kdtm) from fn_test order by kdtm" qt_sql_week_floor_DateTime_notnull "select week_floor(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_week_floor_DateTimeV2 "select week_floor(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_week_floor_TimestampNs "select week_floor(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_week_floor_DateTimeV2_notnull "select week_floor(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_week_floor_TimestampNs_notnull "select week_floor(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_week_floor_DateV2 "select week_floor(kdtv2) from fn_test order by kdtv2" qt_sql_week_floor_DateV2_notnull "select week_floor(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_week_floor_DateTime_DateTime "select week_floor(kdtm, kdtm) from fn_test order by kdtm, kdtm" @@ -66,9 +80,13 @@ suite("nereids_scalar_fn_W") { qt_sql_week_floor_DateTime_Integer "select week_floor(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_week_floor_DateTime_Integer_notnull "select week_floor(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_week_floor_DateTimeV2_DateTimeV2 "select week_floor(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_week_floor_TimestampNs_TimestampNs "select week_floor(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_week_floor_DateTimeV2_DateTimeV2_notnull "select week_floor(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_week_floor_TimestampNs_TimestampNs_notnull "select week_floor(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_week_floor_DateTimeV2_Integer "select week_floor(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_week_floor_TimestampNs_Integer "select week_floor(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_week_floor_DateTimeV2_Integer_notnull "select week_floor(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_week_floor_TimestampNs_Integer_notnull "select week_floor(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_week_floor_DateV2_DateV2 "select week_floor(kdtv2, kdtv2) from fn_test order by kdtv2, kdtv2" qt_sql_week_floor_DateV2_DateV2_notnull "select week_floor(kdtv2, kdtv2) from fn_test_not_nullable order by kdtv2, kdtv2" qt_sql_week_floor_DateV2_Integer "select week_floor(kdtv2, kint) from fn_test order by kdtv2, kint" @@ -76,23 +94,31 @@ suite("nereids_scalar_fn_W") { qt_sql_week_floor_DateTime_Integer_DateTime "select week_floor(kdtm, kint, kdtm) from fn_test order by kdtm, kint, kdtm" qt_sql_week_floor_DateTime_Integer_DateTime_notnull "select week_floor(kdtm, kint, kdtm) from fn_test_not_nullable order by kdtm, kint, kdtm" qt_sql_week_floor_DateTimeV2_Integer_DateTimeV2 "select week_floor(kdtmv2s1, kint, kdtmv2s1) from fn_test order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_week_floor_TimestampNs_Integer_TimestampNs "select week_floor(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_week_floor_DateTimeV2_Integer_DateTimeV2_notnull "select week_floor(kdtmv2s1, kint, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_week_floor_TimestampNs_Integer_TimestampNs_notnull "select week_floor(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_week_floor_DateV2_Integer_DateV2 "select week_floor(kdtv2, kint, kdtv2) from fn_test order by kdtv2, kint, kdtv2" qt_sql_week_floor_DateV2_Integer_DateV2_notnull "select week_floor(kdtv2, kint, kdtv2) from fn_test_not_nullable order by kdtv2, kint, kdtv2" qt_sql_weekday_DateTime "select weekday(kdtm) from fn_test order by kdtm" qt_sql_weekday_DateTime_notnull "select weekday(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_weekday_DateTimeV2 "select weekday(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_weekday_TimestampNs "select weekday(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_weekday_DateTimeV2_notnull "select weekday(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_weekday_TimestampNs_notnull "select weekday(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_weekday_DateV2 "select weekday(kdtv2) from fn_test order by kdtv2" qt_sql_weekday_DateV2_notnull "select weekday(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_weekofyear_DateTime "select weekofyear(kdtm) from fn_test order by kdtm" qt_sql_weekofyear_DateTime_notnull "select weekofyear(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_weekofyear_DateTimeV2 "select weekofyear(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_weekofyear_TimestampNs "select weekofyear(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_weekofyear_DateTimeV2_notnull "select weekofyear(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_weekofyear_TimestampNs_notnull "select weekofyear(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_weekofyear_DateV2 "select weekofyear(kdtv2) from fn_test order by kdtv2" qt_sql_weekofyear_DateV2_notnull "select weekofyear(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_weeks_add_DateTimeV2_Integer "select weeks_add(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_weeks_add_TimestampNs_Integer "select weeks_add(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_weeks_add_DateTimeV2_Integer_notnull "select weeks_add(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_weeks_add_TimestampNs_Integer_notnull "select weeks_add(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_weeks_add_DateV2_Integer "select weeks_add(kdtv2, kint) from fn_test order by kdtv2, kint" qt_sql_weeks_add_DateV2_Integer_notnull "select weeks_add(kdtv2, kint) from fn_test_not_nullable order by kdtv2, kint" qt_sql_weeks_add_DateTime_Integer "select weeks_add(kdtm, kint) from fn_test order by kdtm, kint" @@ -110,11 +136,17 @@ suite("nereids_scalar_fn_W") { qt_sql_weeks_diff_DateTime_DateTime "select weeks_diff(kdtm, kdtm) from fn_test order by kdtm, kdtm" qt_sql_weeks_diff_DateTime_DateTime_notnull "select weeks_diff(kdtm, kdtm) from fn_test_not_nullable order by kdtm, kdtm" qt_sql_weeks_diff_DateTimeV2_DateTimeV2 "select weeks_diff(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_weeks_diff_TimestampNs_TimestampNs "select weeks_diff(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_weeks_diff_DateTimeV2_DateTimeV2_notnull "select weeks_diff(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_weeks_diff_TimestampNs_TimestampNs_notnull "select weeks_diff(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_weeks_diff_DateV2_DateTimeV2 "select weeks_diff(kdtv2, kdtmv2s1) from fn_test order by kdtv2, kdtmv2s1" + qt_sql_weeks_diff_DateV2_TimestampNs "select weeks_diff(kdtv2, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by kdtv2, cast(kdtmv2s1 as timestamp_ns)" qt_sql_weeks_diff_DateV2_DateTimeV2_notnull "select weeks_diff(kdtv2, kdtmv2s1) from fn_test_not_nullable order by kdtv2, kdtmv2s1" + qt_sql_weeks_diff_DateV2_TimestampNs_notnull "select weeks_diff(kdtv2, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by kdtv2, cast(kdtmv2s1 as timestamp_ns)" qt_sql_weeks_diff_DateTimeV2_DateV2 "select weeks_diff(kdtmv2s1, kdtv2) from fn_test order by kdtmv2s1, kdtv2" + qt_sql_weeks_diff_TimestampNs_DateV2 "select weeks_diff(cast(kdtmv2s1 as timestamp_ns), kdtv2) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kdtv2" qt_sql_weeks_diff_DateTimeV2_DateV2_notnull "select weeks_diff(kdtmv2s1, kdtv2) from fn_test_not_nullable order by kdtmv2s1, kdtv2" + qt_sql_weeks_diff_TimestampNs_DateV2_notnull "select weeks_diff(cast(kdtmv2s1 as timestamp_ns), kdtv2) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kdtv2" qt_sql_weeks_diff_DateV2_DateV2 "select weeks_diff(kdtv2, kdtv2) from fn_test order by kdtv2, kdtv2" qt_sql_weeks_diff_DateV2_DateV2_notnull "select weeks_diff(kdtv2, kdtv2) from fn_test_not_nullable order by kdtv2, kdtv2" qt_sql_weeks_diff_DateV2_DateTime "select weeks_diff(kdtv2, kdtm) from fn_test order by kdtv2, kdtm" @@ -122,11 +154,17 @@ suite("nereids_scalar_fn_W") { qt_sql_weeks_diff_DateTime_DateV2 "select weeks_diff(kdtm, kdtv2) from fn_test order by kdtm, kdtv2" qt_sql_weeks_diff_DateTime_DateV2_notnull "select weeks_diff(kdtm, kdtv2) from fn_test_not_nullable order by kdtm, kdtv2" qt_sql_weeks_diff_DateTimeV2_DateTime "select weeks_diff(kdtmv2s1, kdtm) from fn_test order by kdtmv2s1, kdtm" + qt_sql_weeks_diff_TimestampNs_DateTime "select weeks_diff(cast(kdtmv2s1 as timestamp_ns), kdtm) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kdtm" qt_sql_weeks_diff_DateTimeV2_DateTime_notnull "select weeks_diff(kdtmv2s1, kdtm) from fn_test_not_nullable order by kdtmv2s1, kdtm" + qt_sql_weeks_diff_TimestampNs_DateTime_notnull "select weeks_diff(cast(kdtmv2s1 as timestamp_ns), kdtm) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kdtm" qt_sql_weeks_diff_DateTime_DateTimeV2 "select weeks_diff(kdtm, kdtmv2s1) from fn_test order by kdtm, kdtmv2s1" + qt_sql_weeks_diff_DateTime_TimestampNs "select weeks_diff(kdtm, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by kdtm, cast(kdtmv2s1 as timestamp_ns)" qt_sql_weeks_diff_DateTime_DateTimeV2_notnull "select weeks_diff(kdtm, kdtmv2s1) from fn_test_not_nullable order by kdtm, kdtmv2s1" + qt_sql_weeks_diff_DateTime_TimestampNs_notnull "select weeks_diff(kdtm, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by kdtm, cast(kdtmv2s1 as timestamp_ns)" qt_sql_weeks_sub_DateTimeV2_Integer "select weeks_sub(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_weeks_sub_TimestampNs_Integer "select weeks_sub(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_weeks_sub_DateTimeV2_Integer_notnull "select weeks_sub(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_weeks_sub_TimestampNs_Integer_notnull "select weeks_sub(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_weeks_sub_DateV2_Integer "select weeks_sub(kdtv2, kint) from fn_test order by kdtv2, kint" qt_sql_weeks_sub_DateV2_Integer_notnull "select weeks_sub(kdtv2, kint) from fn_test_not_nullable order by kdtv2, kint" qt_sql_weeks_sub_DateTime_Integer "select weeks_sub(kdtm, kint) from fn_test order by kdtm, kint" @@ -162,5 +200,7 @@ suite("nereids_scalar_fn_W") { qt_sql_width_bucket_DateTime_DateTime_DateTime_TinyInt "select width_bucket(kdtm, kdtm, kdtm + interval 1 day, 1) from fn_test order by kdtm, kdtm, kdtm, ktint" qt_sql_width_bucket_DateTime_DateTime_DateTime_TinyInt_notnull "select width_bucket(kdtm, kdtm, kdtm + interval 1 day, 1) from fn_test_not_nullable order by kdtm, kdtm, kdtm, ktint" qt_sql_width_bucket_DateTimeV2_DateTimeV2_DateTimeV2_TinyInt "select width_bucket(kdtmv2s1, kdtmv2s1, kdtmv2s1 + interval 1 day, 1) from fn_test order by kdtmv2s1, kdtmv2s1, kdtmv2s1, ktint" + qt_sql_width_bucket_TimestampNs_TimestampNs_TimestampNs_TinyInt "select width_bucket(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns) + interval 1 day, 1) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns), ktint" qt_sql_width_bucket_DateTimeV2_DateTimeV2_DateTimeV2_TinyInt_notnull "select width_bucket(kdtmv2s1, kdtmv2s1, kdtmv2s1 + interval 1 day, 1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1, kdtmv2s1, ktint" + qt_sql_width_bucket_TimestampNs_TimestampNs_TimestampNs_TinyInt_notnull "select width_bucket(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns) + interval 1 day, 1) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns), ktint" } \ No newline at end of file diff --git a/regression-test/suites/nereids_function_p0/scalar_function/Y.groovy b/regression-test/suites/nereids_function_p0/scalar_function/Y.groovy index bd2f9e65cc4bf7..2c67c564e63c6a 100644 --- a/regression-test/suites/nereids_function_p0/scalar_function/Y.groovy +++ b/regression-test/suites/nereids_function_p0/scalar_function/Y.groovy @@ -24,11 +24,15 @@ suite("nereids_scalar_fn_Y") { qt_sql_year_DateTime "select year(kdtm) from fn_test order by kdtm" qt_sql_year_DateTime_notnull "select year(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_year_DateTimeV2 "select year(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_year_TimestampNs "select year(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_year_DateTimeV2_notnull "select year(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_year_TimestampNs_notnull "select year(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_year_ceil_DateTime "select year_ceil(kdtm) from fn_test order by kdtm" qt_sql_year_ceil_DateTime_notnull "select year_ceil(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_year_ceil_DateTimeV2 "select year_ceil(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_year_ceil_TimestampNs "select year_ceil(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_year_ceil_DateTimeV2_notnull "select year_ceil(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_year_ceil_TimestampNs_notnull "select year_ceil(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_year_ceil_DateV2 "select year_ceil(kdtv2) from fn_test order by kdtv2" qt_sql_year_ceil_DateV2_notnull "select year_ceil(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_year_ceil_DateTime_DateTime "select year_ceil(kdtm, kdtm) from fn_test order by kdtm, kdtm" @@ -36,9 +40,13 @@ suite("nereids_scalar_fn_Y") { qt_sql_year_ceil_DateTime_Integer "select year_ceil(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_year_ceil_DateTime_Integer_notnull "select year_ceil(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_year_ceil_DateTimeV2_DateTimeV2 "select year_ceil(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_year_ceil_TimestampNs_TimestampNs "select year_ceil(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_year_ceil_DateTimeV2_DateTimeV2_notnull "select year_ceil(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_year_ceil_TimestampNs_TimestampNs_notnull "select year_ceil(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_year_ceil_DateTimeV2_Integer "select year_ceil(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_year_ceil_TimestampNs_Integer "select year_ceil(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_year_ceil_DateTimeV2_Integer_notnull "select year_ceil(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_year_ceil_TimestampNs_Integer_notnull "select year_ceil(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_year_ceil_DateV2_DateV2 "select year_ceil(kdtv2, kdtv2) from fn_test order by kdtv2, kdtv2" qt_sql_year_ceil_DateV2_DateV2_notnull "select year_ceil(kdtv2, kdtv2) from fn_test_not_nullable order by kdtv2, kdtv2" qt_sql_year_ceil_DateV2_Integer "select year_ceil(kdtv2, kint) from fn_test order by kdtv2, kint" @@ -46,13 +54,17 @@ suite("nereids_scalar_fn_Y") { qt_sql_year_ceil_DateTime_Integer_DateTime "select year_ceil(kdtm, kint, kdtm) from fn_test order by kdtm, kint, kdtm" qt_sql_year_ceil_DateTime_Integer_DateTime_notnull "select year_ceil(kdtm, kint, kdtm) from fn_test_not_nullable order by kdtm, kint, kdtm" qt_sql_year_ceil_DateTimeV2_Integer_DateTimeV2 "select year_ceil(kdtmv2s1, kint, kdtmv2s1) from fn_test order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_year_ceil_TimestampNs_Integer_TimestampNs "select year_ceil(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_year_ceil_DateTimeV2_Integer_DateTimeV2_notnull "select year_ceil(kdtmv2s1, kint, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_year_ceil_TimestampNs_Integer_TimestampNs_notnull "select year_ceil(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_year_ceil_DateV2_Integer_DateV2 "select year_ceil(kdtv2, kint, kdtv2) from fn_test order by kdtv2, kint, kdtv2" qt_sql_year_ceil_DateV2_Integer_DateV2_notnull "select year_ceil(kdtv2, kint, kdtv2) from fn_test_not_nullable order by kdtv2, kint, kdtv2" qt_sql_year_floor_DateTime "select year_floor(kdtm) from fn_test order by kdtm" qt_sql_year_floor_DateTime_notnull "select year_floor(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_year_floor_DateTimeV2 "select year_floor(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_year_floor_TimestampNs "select year_floor(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_year_floor_DateTimeV2_notnull "select year_floor(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_year_floor_TimestampNs_notnull "select year_floor(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_year_floor_DateV2 "select year_floor(kdtv2) from fn_test order by kdtv2" qt_sql_year_floor_DateV2_notnull "select year_floor(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_year_floor_DateTime_DateTime "select year_floor(kdtm, kdtm) from fn_test order by kdtm, kdtm" @@ -60,9 +72,13 @@ suite("nereids_scalar_fn_Y") { qt_sql_year_floor_DateTime_Integer "select year_floor(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_year_floor_DateTime_Integer_notnull "select year_floor(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_year_floor_DateTimeV2_DateTimeV2 "select year_floor(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_year_floor_TimestampNs_TimestampNs "select year_floor(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_year_floor_DateTimeV2_DateTimeV2_notnull "select year_floor(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_year_floor_TimestampNs_TimestampNs_notnull "select year_floor(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_year_floor_DateTimeV2_Integer "select year_floor(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_year_floor_TimestampNs_Integer "select year_floor(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_year_floor_DateTimeV2_Integer_notnull "select year_floor(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_year_floor_TimestampNs_Integer_notnull "select year_floor(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_year_floor_DateV2_DateV2 "select year_floor(kdtv2, kdtv2) from fn_test order by kdtv2, kdtv2" qt_sql_year_floor_DateV2_DateV2_notnull "select year_floor(kdtv2, kdtv2) from fn_test_not_nullable order by kdtv2, kdtv2" qt_sql_year_floor_DateV2_Integer "select year_floor(kdtv2, kint) from fn_test order by kdtv2, kint" @@ -70,13 +86,17 @@ suite("nereids_scalar_fn_Y") { qt_sql_year_floor_DateTime_Integer_DateTime "select year_floor(kdtm, kint, kdtm) from fn_test order by kdtm, kint, kdtm" qt_sql_year_floor_DateTime_Integer_DateTime_notnull "select year_floor(kdtm, kint, kdtm) from fn_test_not_nullable order by kdtm, kint, kdtm" qt_sql_year_floor_DateTimeV2_Integer_DateTimeV2 "select year_floor(kdtmv2s1, kint, kdtmv2s1) from fn_test order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_year_floor_TimestampNs_Integer_TimestampNs "select year_floor(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_year_floor_DateTimeV2_Integer_DateTimeV2_notnull "select year_floor(kdtmv2s1, kint, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kint, kdtmv2s1" + qt_sql_year_floor_TimestampNs_Integer_TimestampNs_notnull "select year_floor(cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint, cast(kdtmv2s1 as timestamp_ns)" qt_sql_year_floor_DateV2_Integer_DateV2 "select year_floor(kdtv2, kint, kdtv2) from fn_test order by kdtv2, kint, kdtv2" qt_sql_year_floor_DateV2_Integer_DateV2_notnull "select year_floor(kdtv2, kint, kdtv2) from fn_test_not_nullable order by kdtv2, kint, kdtv2" qt_sql_years_add_DateTime_Integer "select years_add(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_years_add_DateTime_Integer_notnull "select years_add(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_years_add_DateTimeV2_Integer "select years_add(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_years_add_TimestampNs_Integer "select years_add(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_years_add_DateTimeV2_Integer_notnull "select years_add(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_years_add_TimestampNs_Integer_notnull "select years_add(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_years_add_Date_Integer "select years_add(kdt, kint) from fn_test order by kdt, kint" qt_sql_years_add_Date_Integer_notnull "select years_add(kdt, kint) from fn_test_not_nullable order by kdt, kint" qt_sql_years_add_DateV2_Integer "select years_add(kdtv2, kint) from fn_test order by kdtv2, kint" @@ -84,11 +104,17 @@ suite("nereids_scalar_fn_Y") { qt_sql_years_diff_DateTime_DateTime "select years_diff(kdtm, kdtm) from fn_test order by kdtm, kdtm" qt_sql_years_diff_DateTime_DateTime_notnull "select years_diff(kdtm, kdtm) from fn_test_not_nullable order by kdtm, kdtm" qt_sql_years_diff_DateTimeV2_DateTimeV2 "select years_diff(kdtmv2s1, kdtmv2s1) from fn_test order by kdtmv2s1, kdtmv2s1" + qt_sql_years_diff_TimestampNs_TimestampNs "select years_diff(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_years_diff_DateTimeV2_DateTimeV2_notnull "select years_diff(kdtmv2s1, kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1, kdtmv2s1" + qt_sql_years_diff_TimestampNs_TimestampNs_notnull "select years_diff(cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), cast(kdtmv2s1 as timestamp_ns)" qt_sql_years_diff_DateV2_DateTimeV2 "select years_diff(kdtv2, kdtmv2s1) from fn_test order by kdtv2, kdtmv2s1" + qt_sql_years_diff_DateV2_TimestampNs "select years_diff(kdtv2, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by kdtv2, cast(kdtmv2s1 as timestamp_ns)" qt_sql_years_diff_DateV2_DateTimeV2_notnull "select years_diff(kdtv2, kdtmv2s1) from fn_test_not_nullable order by kdtv2, kdtmv2s1" + qt_sql_years_diff_DateV2_TimestampNs_notnull "select years_diff(kdtv2, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by kdtv2, cast(kdtmv2s1 as timestamp_ns)" qt_sql_years_diff_DateTimeV2_DateV2 "select years_diff(kdtmv2s1, kdtv2) from fn_test order by kdtmv2s1, kdtv2" + qt_sql_years_diff_TimestampNs_DateV2 "select years_diff(cast(kdtmv2s1 as timestamp_ns), kdtv2) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kdtv2" qt_sql_years_diff_DateTimeV2_DateV2_notnull "select years_diff(kdtmv2s1, kdtv2) from fn_test_not_nullable order by kdtmv2s1, kdtv2" + qt_sql_years_diff_TimestampNs_DateV2_notnull "select years_diff(cast(kdtmv2s1 as timestamp_ns), kdtv2) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kdtv2" qt_sql_years_diff_DateV2_DateV2 "select years_diff(kdtv2, kdtv2) from fn_test order by kdtv2, kdtv2" qt_sql_years_diff_DateV2_DateV2_notnull "select years_diff(kdtv2, kdtv2) from fn_test_not_nullable order by kdtv2, kdtv2" qt_sql_years_diff_DateV2_DateTime "select years_diff(kdtv2, kdtm) from fn_test order by kdtv2, kdtm" @@ -96,13 +122,19 @@ suite("nereids_scalar_fn_Y") { qt_sql_years_diff_DateTime_DateV2 "select years_diff(kdtm, kdtv2) from fn_test order by kdtm, kdtv2" qt_sql_years_diff_DateTime_DateV2_notnull "select years_diff(kdtm, kdtv2) from fn_test_not_nullable order by kdtm, kdtv2" qt_sql_years_diff_DateTimeV2_DateTime "select years_diff(kdtmv2s1, kdtm) from fn_test order by kdtmv2s1, kdtm" + qt_sql_years_diff_TimestampNs_DateTime "select years_diff(cast(kdtmv2s1 as timestamp_ns), kdtm) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kdtm" qt_sql_years_diff_DateTimeV2_DateTime_notnull "select years_diff(kdtmv2s1, kdtm) from fn_test_not_nullable order by kdtmv2s1, kdtm" + qt_sql_years_diff_TimestampNs_DateTime_notnull "select years_diff(cast(kdtmv2s1 as timestamp_ns), kdtm) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kdtm" qt_sql_years_diff_DateTime_DateTimeV2 "select years_diff(kdtm, kdtmv2s1) from fn_test order by kdtm, kdtmv2s1" + qt_sql_years_diff_DateTime_TimestampNs "select years_diff(kdtm, cast(kdtmv2s1 as timestamp_ns)) from fn_test order by kdtm, cast(kdtmv2s1 as timestamp_ns)" qt_sql_years_diff_DateTime_DateTimeV2_notnull "select years_diff(kdtm, kdtmv2s1) from fn_test_not_nullable order by kdtm, kdtmv2s1" + qt_sql_years_diff_DateTime_TimestampNs_notnull "select years_diff(kdtm, cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by kdtm, cast(kdtmv2s1 as timestamp_ns)" qt_sql_years_sub_DateTime_Integer "select years_sub(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_years_sub_DateTime_Integer_notnull "select years_sub(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_years_sub_DateTimeV2_Integer "select years_sub(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_years_sub_TimestampNs_Integer "select years_sub(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_years_sub_DateTimeV2_Integer_notnull "select years_sub(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_years_sub_TimestampNs_Integer_notnull "select years_sub(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_years_sub_Date_Integer "select years_sub(kdt, kint) from fn_test order by kdt, kint" qt_sql_years_sub_Date_Integer_notnull "select years_sub(kdt, kint) from fn_test_not_nullable order by kdt, kint" qt_sql_years_sub_DateV2_Integer "select years_sub(kdtv2, kint) from fn_test order by kdtv2, kint" @@ -110,13 +142,17 @@ suite("nereids_scalar_fn_Y") { qt_sql_yearweek_DateTime "select yearweek(kdtm) from fn_test order by kdtm" qt_sql_yearweek_DateTime_notnull "select yearweek(kdtm) from fn_test_not_nullable order by kdtm" qt_sql_yearweek_DateTimeV2 "select yearweek(kdtmv2s1) from fn_test order by kdtmv2s1" + qt_sql_yearweek_TimestampNs "select yearweek(cast(kdtmv2s1 as timestamp_ns)) from fn_test order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_yearweek_DateTimeV2_notnull "select yearweek(kdtmv2s1) from fn_test_not_nullable order by kdtmv2s1" + qt_sql_yearweek_TimestampNs_notnull "select yearweek(cast(kdtmv2s1 as timestamp_ns)) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns)" qt_sql_yearweek_DateV2 "select yearweek(kdtv2) from fn_test order by kdtv2" qt_sql_yearweek_DateV2_notnull "select yearweek(kdtv2) from fn_test_not_nullable order by kdtv2" qt_sql_yearweek_DateTime_Integer "select yearweek(kdtm, kint) from fn_test order by kdtm, kint" qt_sql_yearweek_DateTime_Integer_notnull "select yearweek(kdtm, kint) from fn_test_not_nullable order by kdtm, kint" qt_sql_yearweek_DateTimeV2_Integer "select yearweek(kdtmv2s1, kint) from fn_test order by kdtmv2s1, kint" + qt_sql_yearweek_TimestampNs_Integer "select yearweek(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_yearweek_DateTimeV2_Integer_notnull "select yearweek(kdtmv2s1, kint) from fn_test_not_nullable order by kdtmv2s1, kint" + qt_sql_yearweek_TimestampNs_Integer_notnull "select yearweek(cast(kdtmv2s1 as timestamp_ns), kint) from fn_test_not_nullable order by cast(kdtmv2s1 as timestamp_ns), kint" qt_sql_yearweek_DateV2_Integer "select yearweek(kdtv2, kint) from fn_test order by kdtv2, kint" qt_sql_yearweek_DateV2_Integer_notnull "select yearweek(kdtv2, kint) from fn_test_not_nullable order by kdtv2, kint" } \ No newline at end of file diff --git a/regression-test/suites/nereids_function_p0/test_timestamp_arithmetic.sql b/regression-test/suites/nereids_function_p0/test_timestamp_arithmetic.sql index 98685479957264..7a3a74deb4c5d4 100644 --- a/regression-test/suites/nereids_function_p0/test_timestamp_arithmetic.sql +++ b/regression-test/suites/nereids_function_p0/test_timestamp_arithmetic.sql @@ -138,3 +138,35 @@ select interval 1 minute + kdtmv2s3 from fn_test_not_nullable order by kdt; select interval 1 second + kdtmv2s3 from fn_test_not_nullable order by kdt; select kdtmv2s3 - interval 1 day from fn_test_not_nullable order by kdt; select kdtmv2s3 - interval 1 second from fn_test_not_nullable order by kdt; +select cast(kdtmv2s3 as timestamp_ns) + interval 1 year from fn_test order by kdt; +select cast(kdtmv2s3 as timestamp_ns) + interval 1 month from fn_test order by kdt; +select cast(kdtmv2s3 as timestamp_ns) + interval 1 week from fn_test order by kdt; +select cast(kdtmv2s3 as timestamp_ns) + interval 1 day from fn_test order by kdt; +select cast(kdtmv2s3 as timestamp_ns) + interval 1 hour from fn_test order by kdt; +select cast(kdtmv2s3 as timestamp_ns) + interval 1 minute from fn_test order by kdt; +select cast(kdtmv2s3 as timestamp_ns) + interval 1 second from fn_test order by kdt; +select interval 1 year + cast(kdtmv2s3 as timestamp_ns) from fn_test order by kdt; +select interval 1 month + cast(kdtmv2s3 as timestamp_ns) from fn_test order by kdt; +select interval 1 week + cast(kdtmv2s3 as timestamp_ns) from fn_test order by kdt; +select interval 1 day + cast(kdtmv2s3 as timestamp_ns) from fn_test order by kdt; +select interval 1 hour + cast(kdtmv2s3 as timestamp_ns) from fn_test order by kdt; +select interval 1 minute + cast(kdtmv2s3 as timestamp_ns) from fn_test order by kdt; +select interval 1 second + cast(kdtmv2s3 as timestamp_ns) from fn_test order by kdt; +select cast(kdtmv2s3 as timestamp_ns) - interval 1 day from fn_test order by kdt; +select cast(kdtmv2s3 as timestamp_ns) - interval 1 second from fn_test order by kdt; +select cast(kdtmv2s3 as timestamp_ns) + interval 1 year from fn_test_not_nullable order by kdt; +select cast(kdtmv2s3 as timestamp_ns) + interval 1 month from fn_test_not_nullable order by kdt; +select cast(kdtmv2s3 as timestamp_ns) + interval 1 week from fn_test_not_nullable order by kdt; +select cast(kdtmv2s3 as timestamp_ns) + interval 1 day from fn_test_not_nullable order by kdt; +select cast(kdtmv2s3 as timestamp_ns) + interval 1 hour from fn_test_not_nullable order by kdt; +select cast(kdtmv2s3 as timestamp_ns) + interval 1 minute from fn_test_not_nullable order by kdt; +select cast(kdtmv2s3 as timestamp_ns) + interval 1 second from fn_test_not_nullable order by kdt; +select interval 1 year + cast(kdtmv2s3 as timestamp_ns) from fn_test_not_nullable order by kdt; +select interval 1 month + cast(kdtmv2s3 as timestamp_ns) from fn_test_not_nullable order by kdt; +select interval 1 week + cast(kdtmv2s3 as timestamp_ns) from fn_test_not_nullable order by kdt; +select interval 1 day + cast(kdtmv2s3 as timestamp_ns) from fn_test_not_nullable order by kdt; +select interval 1 hour + cast(kdtmv2s3 as timestamp_ns) from fn_test_not_nullable order by kdt; +select interval 1 minute + cast(kdtmv2s3 as timestamp_ns) from fn_test_not_nullable order by kdt; +select interval 1 second + cast(kdtmv2s3 as timestamp_ns) from fn_test_not_nullable order by kdt; +select cast(kdtmv2s3 as timestamp_ns) - interval 1 day from fn_test_not_nullable order by kdt; +select cast(kdtmv2s3 as timestamp_ns) - interval 1 second from fn_test_not_nullable order by kdt;