Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion datafusion/common/src/scalar/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3069,7 +3069,7 @@ impl ScalarValue {
ScalarValue::Decimal128(Some(decimal_value), _, scale),
DataType::Timestamp(time_unit, None),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In #16639 i tried to clear the path for more changes here.
If and once that one merged, we should be able to remove this whole code block.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#16639 is now merged.
please remove the whole let scalar_array = match (self, target_type) { ... } block, replacing it with just self.to_array()?.

) => {
let scale_factor = 10_i128.pow(*scale as u32);
let scale_factor = 10_i128.pow(*scale as u32 + 3);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this depend on the timestamp precision (time unit)? Can you please add tests for other units?

Do we need this special casing at all for casting decimal to timestamp?
or can we end up calling cast_with_options, just like we do for virtually all other type pairs?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the underlying arrow kernel may not support casting decimal --> timestamp (I bet this is something spark related) 🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the underlying arrow kernel may not support casting decimal --> timestamp (I bet this is something spark related) 🤔
@alamb here implements casting decimal --> timestamp
https://github.com/apache/arrow-rs/blob/b6240b32e235d4ca330372e3be31f784ba133252/arrow-cast/src/cast/mod.rs#L4032

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this depend on the timestamp precision (time unit)? Can you please add tests for other units?

Do we need this special casing at all for casting decimal to timestamp? or can we end up calling cast_with_options, just like we do for virtually all other type pairs?

@findepi you are right, it's time unit related. I updated code.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the underlying arrow kernel may not support casting decimal --> timestamp

Can be!

So how does this work when the value is not constant-folded?
What code ends up executing in the 'normal query' case?

Can the same code be executed also in constant-folding case?

let seconds = decimal_value / scale_factor;
let fraction = decimal_value % scale_factor;

Expand Down
13 changes: 9 additions & 4 deletions datafusion/sqllogictest/test_files/timestamps.slt
Original file line number Diff line number Diff line change
Expand Up @@ -421,12 +421,12 @@ SELECT to_timestamp(123456789.123456789) as c1, cast(123456789.123456789 as time
query PPP
SELECT to_timestamp(arrow_cast(1.1, 'Decimal128(2,1)')) as c1, cast(arrow_cast(1.1, 'Decimal128(2,1)') as timestamp) as c2, arrow_cast(1.1, 'Decimal128(2,1)')::timestamp as c3;
----
1970-01-01T00:00:01.100 1970-01-01T00:00:01.100 1970-01-01T00:00:01.100
1970-01-01T00:00:01.100 1970-01-01T00:00:00.001100 1970-01-01T00:00:00.001100

query PPP
SELECT to_timestamp(arrow_cast(-1.1, 'Decimal128(2,1)')) as c1, cast(arrow_cast(-1.1, 'Decimal128(2,1)') as timestamp) as c2, arrow_cast(-1.1, 'Decimal128(2,1)')::timestamp as c3;
----
1969-12-31T23:59:58.900 1969-12-31T23:59:58.900 1969-12-31T23:59:58.900
1969-12-31T23:59:58.900 1969-12-31T23:59:59.998900 1969-12-31T23:59:59.998900

query PPP
SELECT to_timestamp(arrow_cast(0.0, 'Decimal128(2,1)')) as c1, cast(arrow_cast(0.0, 'Decimal128(2,1)') as timestamp) as c2, arrow_cast(0.0, 'Decimal128(2,1)')::timestamp as c3;
Expand All @@ -436,12 +436,12 @@ SELECT to_timestamp(arrow_cast(0.0, 'Decimal128(2,1)')) as c1, cast(arrow_cast(0
query PPP
SELECT to_timestamp(arrow_cast(1.23456789, 'Decimal128(9,8)')) as c1, cast(arrow_cast(1.23456789, 'Decimal128(9,8)') as timestamp) as c2, arrow_cast(1.23456789, 'Decimal128(9,8)')::timestamp as c3;
----
1970-01-01T00:00:01.234567890 1970-01-01T00:00:01.234567890 1970-01-01T00:00:01.234567890
1970-01-01T00:00:01.234567890 1970-01-01T00:00:00.001234567 1970-01-01T00:00:00.001234567

query PPP
SELECT to_timestamp(arrow_cast(123456789.123456789, 'Decimal128(18,9)')) as c1, cast(arrow_cast(123456789.123456789, 'Decimal128(18,9)') as timestamp) as c2, arrow_cast(123456789.123456789, 'Decimal128(18,9)')::timestamp as c3;
----
1973-11-29T21:33:09.123456784 1973-11-29T21:33:09.123456784 1973-11-29T21:33:09.123456784
1973-11-29T21:33:09.123456784 1970-01-02T10:17:36.789123456 1970-01-02T10:17:36.789123456


# from_unixtime
Expand Down Expand Up @@ -3420,3 +3420,8 @@ select to_timestamp('-1');

query error DataFusion error: Arrow error: Parser error: Error parsing timestamp from '\-1': timestamp must contain at least 10 characters
select to_timestamp(arrow_cast('-1', 'Utf8'));

query B
SELECT CAST(CAST(x AS decimal(17,2)) AS timestamp(3)) = CAST(CAST(1 AS decimal(17,2)) AS timestamp(3)) from (values (1)) t(x);
----

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting like this will help see why these should be equal. Also it's enough to project the values. (They should be equal, but also they should be particular values).

SELECT CAST(CAST(1   AS decimal(17,2)) AS timestamp(3)) AS a UNION ALL
SELECT CAST(CAST(one AS decimal(17,2)) AS timestamp(3)) AS a FROM (VALUES (1)) t(one);

true