@@ -158,6 +158,18 @@ Literal Literal::Fixed(std::vector<uint8_t> value) {
158158 return {Value{std::move (value)}, fixed (length)};
159159}
160160
161+ Literal Literal::MakeDecimal (Decimal value, int32_t precision, int32_t scale) {
162+ return {Value{value}, decimal (precision, scale)};
163+ }
164+
165+ Result<Literal> Literal::MakeDecimal (std::string_view value) {
166+ int32_t precision = 0 ;
167+ int32_t scale = 0 ;
168+ ICEBERG_ASSIGN_OR_RAISE (auto decimal_value,
169+ Decimal::FromString (value, &precision, &scale));
170+ return Literal{Value{decimal_value}, decimal (precision, scale)};
171+ }
172+
161173Result<Literal> Literal::Deserialize (std::span<const uint8_t > data,
162174 std::shared_ptr<PrimitiveType> type) {
163175 return Conversions::FromBytes (std::move (type), data);
@@ -193,12 +205,44 @@ std::strong_ordering CompareFloat(T lhs, T rhs) {
193205 return lhs_is_negative <=> rhs_is_negative;
194206}
195207
208+ std::strong_ordering CompareDecimal (Literal const & lhs, Literal const & rhs) {
209+ ICEBERG_DCHECK (std::holds_alternative<Decimal>(lhs.value ()),
210+ " LHS of decimal comparison must hold Decimal" );
211+ ICEBERG_DCHECK (std::holds_alternative<Decimal>(rhs.value ()),
212+ " RHS of decimal comparison must hold decimal" );
213+ const auto & lhs_type = std::dynamic_pointer_cast<DecimalType>(lhs.type ());
214+ const auto & rhs_type = std::dynamic_pointer_cast<DecimalType>(rhs.type ());
215+ ICEBERG_DCHECK (lhs_type != nullptr , " LHS type must be DecimalType" );
216+ ICEBERG_DCHECK (rhs_type != nullptr , " RHS type must be DecimalType" );
217+ auto lhs_decimal = std::get<Decimal>(lhs.value ());
218+ auto rhs_decimal = std::get<Decimal>(rhs.value ());
219+ if (lhs_type->scale () == rhs_type->scale ()) {
220+ return lhs_decimal <=> rhs_decimal;
221+ } else if (lhs_type->scale () > rhs_type->scale ()) {
222+ // Rescale to larger scale
223+ auto rhs_res = rhs_decimal.Rescale (rhs_type->scale (), lhs_type->scale ());
224+ if (!rhs_res) {
225+ // Rescale would cause data loss, so lhs is definitely less than rhs
226+ return std::strong_ordering::less;
227+ }
228+ return lhs_decimal <=> rhs_res.value ();
229+ } else {
230+ // Rescale to larger scale
231+ auto lhs_res = lhs_decimal.Rescale (lhs_type->scale (), rhs_type->scale ());
232+ if (!lhs_res) {
233+ // Rescale would cause data loss, so lhs is definitely greater than rhs
234+ return std::strong_ordering::greater;
235+ }
236+ return lhs_res.value () <=> rhs_decimal;
237+ }
238+ }
239+
196240bool Literal::operator ==(const Literal& other) const { return (*this <=> other) == 0 ; }
197241
198242// Three-way comparison operator
199243std::partial_ordering Literal::operator <=>(const Literal& other) const {
200244 // If types are different, comparison is unordered
201- if (* type_ != * other.type_ ) {
245+ if (type_-> type_id () != other.type_ -> type_id () ) {
202246 return std::partial_ordering::unordered;
203247 }
204248
@@ -247,6 +291,10 @@ std::partial_ordering Literal::operator<=>(const Literal& other) const {
247291 return CompareFloat (this_val, other_val);
248292 }
249293
294+ case TypeId::kDecimal : {
295+ return CompareDecimal (*this , other);
296+ }
297+
250298 case TypeId::kString : {
251299 auto & this_val = std::get<std::string>(value_);
252300 auto & other_val = std::get<std::string>(other.value_ );
@@ -307,6 +355,14 @@ std::string Literal::ToString() const {
307355 case TypeId::kDouble : {
308356 return std::to_string (std::get<double >(value_));
309357 }
358+ case TypeId::kDecimal : {
359+ auto decimal = std::get<Decimal>(value_);
360+ auto decimal_type = std::dynamic_pointer_cast<DecimalType>(type_);
361+ ICEBERG_DCHECK (decimal_type != nullptr , " Type must be DecimalType" );
362+ auto result = decimal.ToString (decimal_type->scale ());
363+ ICEBERG_CHECK (result, " Decimal ToString failed" );
364+ return *result;
365+ }
310366 case TypeId::kString : {
311367 return std::get<std::string>(value_);
312368 }
@@ -331,7 +387,6 @@ std::string Literal::ToString() const {
331387 }
332388 return result;
333389 }
334- case TypeId::kDecimal :
335390 case TypeId::kDate :
336391 case TypeId::kTime :
337392 case TypeId::kTimestamp :
0 commit comments