New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NiFi-2829: Add Date and Time Format Support for PutSQL #1983
Conversation
Well, lesson learned. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Posted a few minor comments but looks good overall.Thanks @yjhyjhyjh0 for your contribution!
Just FYI, a commit message should use uppercase 'NIFI-XXXX' so that a PR is automatically linked to the JIRA.
date = new Date(Long.parseLong(parameterValue)); | ||
}else { | ||
String dateFormatString = "yyyy-MM-dd"; | ||
if (!valueFormat.isEmpty()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This condition won't be true as it already checks valueFormat.equals("")
above. BTW, I personally prefer isEmpty()
than equals("")
. Existing code for TIMESTAMP uses equals("")
though.
time = new Time(Long.parseLong(parameterValue)); | ||
} else { | ||
String timeFormatString = "HH:mm:ss.SSS"; | ||
if (!valueFormat.isEmpty()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as DATE, this won't be true.
+ "hex: the string is hex encoded with all letters in upper case and no '0x' at the beginning. " | ||
+ "Dates/Times/Timestamps - " | ||
+ "Date, Time and Timestamp formats all support both custom formats or named format ('yyyy-MM-dd','ISO_OFFSET_DATE_TIME') " | ||
+ "as specified according to java.time.format.DateTimeFormatter.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice documentation! How about adding default behavior as well? Such as "If not specified, a long value input is expected to be an unix epoch (milli seconds from 1970/1/1) or 'yyyy-MM-dd' format is used."
if (valueFormat.equals("")) { | ||
if(LONG_PATTERN.matcher(parameterValue).matches()){ | ||
date = new Date(Long.parseLong(parameterValue)); | ||
}else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We prefer to have a space here, like } else {
. The existing code for TIMESTAMP has the similar code, too.
Thanks for the reply and detail review. Seems AppVevor fail at same part. |
@yjhyjhyjh0 Thanks for the updates! For AppVeyor test, it has been failing and Travis test failure is caused by nifi-persistent-provenance-repository, which has also been failing occasionally, so please don't worry about those. I'll continue reviewing.. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yjhyjhyjh0 I've finished testing this with MySQL and PostgreSQL. Found an possible improvement with TIME type and millisecond support. Please see my comment. That is my last feedback to this PR. Once the comment is addressed, I'm going to merge this. Thank you!
} else { | ||
final DateTimeFormatter dtFormatter = getDateTimeFormatter(valueFormat); | ||
LocalTime parsedTime = LocalTime.parse(parameterValue, dtFormatter); | ||
time = Time.valueOf(parsedTime); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some databases support fractional seconds (milli or microseconds). By creating java.sql.Time instance from LocalTime, even if the LocalTime has fractional seconds, it will be truncated because Time.valueOf only uses hours, minutes and seconds as follows:
java.sql.Time
public static Time valueOf(LocalTime time) {
return new Time(time.getHour(), time.getMinute(), time.getSecond());
}
Can we have this like this instead? This way, we can preserve time precision at milliseconds if the database driver and database server supports it:
final DateTimeFormatter dtFormatter = getDateTimeFormatter(valueFormat);
LocalTime parsedTime = LocalTime.parse(parameterValue, dtFormatter);
LocalDateTime localDateTime = parsedTime.atDate(LocalDate.ofEpochDay(0));
Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
time = new Time(instant.toEpochMilli());
I confirmed this behavior with MySQL and PostgreSQL. With PostgreSQL, before changing this, when I passed "18:25:43.511" JSON value with ISO_LOCAL_TIME format, it's stored without milliseconds, "18:25:43". With above change, using new Time(Long) constructor, I was able to preserve milliseconds "18:25:43.511".
Unfortunately MySQL JDBC Driver has a known issue that it truncates milliseconds 76775, so we can't store millisecond with MySQL currently (TIMESTAMP works though).
Fix unit test for Date and Time type time zone problem Enhance Time type to record milliseconds
Thanks for the review and feedback. However after some experiment, I figure out Derby DB has same behavior as MySQL in Time type just like what you mentioned. About the experiment, it store Time type well with value "00:01:01.111" in PutSQL. Thus, I only update document to remind this situation instead of providing a unit test for this format. |
I've made a slight change to the documentation to state MySQL and Derby are some database engines that do not support milliseconds, but those may not be the only two. I am fine with not having unit test for it as we use Derby, clarify it via docs should be enough. |
As this PR is based on #1524 which was submitted by @patricker , I cherry-picked #1524 first, then cherry-picked this PR to give @patricker a credit. Thanks again! |
Fix unit test for Date and Time type time zone problem while testing PutSQL processor
@paulgibeault made the original PR #1073, #1468
@patricker add support of DATE and TIME in Epoch format for PutSQL processor.
I’ve fix the unit test in different time zone problem.
The detail is list below
The originally problem with unit test happens because of different time zone.
Internally without specifying time zone, java.sql.Date and java.sql.Time will use local time zone to parse the time.
As a result, different time zone will have different format result for a given constant time value.
This is mentioned by @mattyb149 in #1524
Currently solve the problem by giving time zone before insert and parse result with same time zone. (GMT)
Currently build and test successfully with NiFi newest version on GitHub which is 1.4.0-SNAPSHOT.
For all changes:
Is there a JIRA ticket associated with this PR? Is it referenced
in the commit message?
Does your PR title start with NIFI-XXXX where XXXX is the JIRA number you are trying to resolve? Pay particular attention to the hyphen "-" character.
Has your PR been rebased against the latest commit within the target branch (typically master)?
Is your initial contribution a single, squashed commit?
For code changes:
For documentation related changes:
Note:
Please ensure that once the PR is submitted, you check travis-ci for build issues and submit an update to your PR as soon as possible.