Skip to content

[CALCITE-3612] Add TIME/TIMESTAMP WITH TIME ZONE in optimizer#1687

Open
docete wants to merge 4 commits intoapache:mainfrom
docete:CALCITE-3612
Open

[CALCITE-3612] Add TIME/TIMESTAMP WITH TIME ZONE in optimizer#1687
docete wants to merge 4 commits intoapache:mainfrom
docete:CALCITE-3612

Conversation

@docete
Copy link
Contributor

@docete docete commented Dec 25, 2019

  • Introduce TIME/TIMESTAMP WITH TIME ZONE types
  • Introduce TimeWithTimeZone as internal representation of TIME WITH TIME ZONE type
  • Introduce TimestampWithTimeZone as internal representation of TIMESTAMP WITH TIME ZONE type
  • Introduce coercion rules for TIME/TIMESTAMP WITH TIME ZONE types

Copy link
Contributor

@amaliujia amaliujia left a comment

Choose a reason for hiding this comment

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

Thanks for you PR!

import org.apache.calcite.util.ControlFlowException;
import org.apache.calcite.util.Pair;
import org.apache.calcite.util.Util;
import org.apache.calcite.util.*;
Copy link
Contributor

Choose a reason for hiding this comment

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

Don't use *, import classes one by one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure

return scaleIntervalToNumber(sourceType, targetType, convert);
}

private Expression converterToDate(RelDataType sourceType, Expression operand) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I would prefer to split this refactoring with adding the new types into two PRs, as it will make clear what is added by this PR and what is newly added code. By doing so we could better review the new code.

Let's see what are other reviewers' opinions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The aim of the refactoring is make sure the length of a method is smaller than 370, and avoid complaining by checkstyle. I will split the refactoring part to a separate commit, that would clarify the PR.

case TIME_WITH_TIME_ZONE:
return new TimeWithTimeZoneString(0, 0, 0, "UTC");
case TIMESTAMP_WITH_TIME_ZONE:
return new TimestampWithTimeZoneString(0, 0, 0, 0, 0, 0, "UTC");
Copy link
Contributor

@amaliujia amaliujia Dec 25, 2019

Choose a reason for hiding this comment

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

Shouldn't 0 is January 1, 1970 UTC, assuming the millis are epoch millis (count from 1970-01-01 UTC)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

After double checked the ZERO of TIMESTAMP type, I think your are right. ZERO should be January 1, 1970 UTC.

return false;
}
TimeWithTimeZone that = (TimeWithTimeZone) obj;
return milliOfDay == that.milliOfDay && timeZone == that.timeZone;
Copy link
Contributor

Choose a reason for hiding this comment

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

Should call timeZone.equals(that.timeZone) otherwise it is comparing the reference but not real value?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, you're right.

public class TimestampWithTimeZone implements Comparable<TimestampWithTimeZone>, Serializable {
//~ Instance fields --------------------------------------------------------

private final long millisecond;
Copy link
Contributor

Choose a reason for hiding this comment

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

is this epoch millis or just millis? If it is epoch millis, can you update comments to reflect it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The millisecond should be a zone-less TIMESTAMP(the internal representation of TIMESTAMP WITHOUT TIME ZONE). The java doc of the constructor has made it clearly.

Copy link
Contributor

Choose a reason for hiding this comment

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

Can you point to me the class that represents TIMESTAMP WITHOUT TIME ZONE in Calcite? I want to double check what type of millis that saves internally?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just a long value. You can see BuiltInMethod.STRING_TO_TIMESTAMP

return false;
}
TimestampWithTimeZone that = (TimestampWithTimeZone) obj;
return this.millisecond == that.millisecond && this.timeZone == that.timeZone;
Copy link
Contributor

Choose a reason for hiding this comment

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

this.timeZone.equals(that.timeZone)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK

import org.apache.calcite.util.TimestampString;
import org.apache.calcite.util.TimestampWithTimeZoneString;
import org.apache.calcite.util.Util;
import org.apache.calcite.util.*;
Copy link
Contributor

@amaliujia amaliujia Dec 25, 2019

Choose a reason for hiding this comment

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

Don't use *. Import classes one by one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK

final RexLiteral literalTimestampWithTZ =
rexBuilder.makeTimestampWithTimeZoneLiteral(
new TimestampWithTimeZoneString(
new TimestampString(2017, 7, 20, 8, 23, 45),
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you test up to millis?

Copy link
Contributor Author

@docete docete Dec 25, 2019

Choose a reason for hiding this comment

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

I noticed the TIMESTAMP and TIMESTAMP WITH LOCAL TIME ZONE also ignored precision in RexToLixTranslator. See cast(TIMESTAMP as CHAR), I think we should follow that. And we could open another ticket to support precision of them.

.getMillisSinceEpoch();
}

public static int timeWithTimeZoneToTime(TimeWithTimeZone ttz) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need javadoc for these public static methods?

Copy link
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 method name has documented it?

@docete
Copy link
Contributor Author

docete commented Dec 25, 2019

rebased to split the refactoring to a separate commit.

// SQL 2011 Part2 Section 4.6 General Rules 13.d
case TIMESTAMP_WITH_TIME_ZONE:
convert = Expressions.convert_(
Expressions.call(BuiltInMethod.FLOOR_DIV.method,
Copy link
Contributor

Choose a reason for hiding this comment

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

implement a timestampWithoutTimeZoneToDate and call it here?

Copy link
Contributor Author

@docete docete Dec 27, 2019

Choose a reason for hiding this comment

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

Not needed!

  1. Section 6.13 General Rules 13.d shows this can be computed as "CAST ( CAST ( VE AS TIMESTAMP WITHOUT TIME ZONE ) AS DATE )"
  2. the underlying TimestampWithTimeZone holds the same long value with Timestamp type, current implementation is more simple

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes. By reading the SQL standard I got the idea of the conversion path.

This suggestion is more from readability perspective. If you implements one more function that then code readers will know the equivalent implementation is CAST ( CAST ( VE AS TIMESTAMP WITHOUT TIME ZONE ) AS DATE ).

I had to read SQL standard cause I wasn't sure why there is a "magic" operation after casting to TIMESTAMP WITHOUT TIME ZONE.

Or maybe you can add a comment instead to say the implementation here is CAST ( CAST ( VE AS TIMESTAMP WITHOUT TIME ZONE ) AS DATE )

Expressions.call(BuiltInMethod.TIME_ZONE.method, root)));
break;
// SQL 2011 Part2 Section 4.6 General Rules 15.e
case TIMESTAMP_WITH_TIME_ZONE:
Copy link
Contributor

Choose a reason for hiding this comment

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

implement a timestampWithoutTimeZoneToTimeWithoutTimeZone and call it here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ditto

operand,
Expressions.call(BuiltInMethod.TIME_ZONE.method, root)));
break;
// SQL 2011 Part2 Section 4.6 General Rules 15.e
Copy link
Contributor

Choose a reason for hiding this comment

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

I didn't find "general rules" under section 4.6 (was looking at page no.36)

SQL 2011 Part2 Section 4.6 Table 3 gives a very clear conversion table.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, it should be Section 6.13 (begin with p243)

return localTime + " " + ttz.getTimeZone().getID();
}

public static TimeWithTimeZone toTimeWithTimeZone(String v, TimeZone sesstionTimeZone) {
Copy link
Contributor

Choose a reason for hiding this comment

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

rename to stringToTimeWithTimeZone?

return new TimeWithTimeZone(milliOfDay, tstz.getTimeZone());
}

public static TimestampWithTimeZone toTimestampWithTimeZone(String v, TimeZone sessionTimeZone) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe also rename and include string?

public class TimestampWithTimeZone implements Comparable<TimestampWithTimeZone>, Serializable {
//~ Instance fields --------------------------------------------------------

private final long millisecond;
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you point to me the class that represents TIMESTAMP WITHOUT TIME ZONE in Calcite? I want to double check what type of millis that saves internally?

docete added 4 commits January 7, 2020 17:27
* Introduce TIME/TIMESTAMP WITH TIME ZONE types
* Introduce TimeWithTimeZone as internal representation of TIME WITH TIME ZONE type
* Introduce TimestampWithTimeZone as internal representation of TIMESTAMP WITH TIME ZONE type
* Introduce coercion rules for TIME/TIMESTAMP WITH TIME ZONE types
@docete
Copy link
Contributor Author

docete commented Jan 7, 2020

rebase to resolve all conflicts

@docete
Copy link
Contributor Author

docete commented Jan 7, 2020

@julianhyde Could you take a look at this if you are free? Hopefully I touched all the right places and didn't missing any thing.

@amaliujia
Copy link
Contributor

@docete

Would you like to pick up this work again? I can help on review/merge your work.

@docete
Copy link
Contributor Author

docete commented Sep 24, 2020

@amaliujia Sorry for the late reply, I will rebase this PR in recent days.

@ian-bertolacci
Copy link

What's the status of this work? Is there someone that can get this to completion? This is a pretty significant hole in Calcite's SQL support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants