Skip to content
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

expression: handle zero date in date_add() #20015

Closed
wants to merge 4 commits into from
Closed

expression: handle zero date in date_add() #20015

wants to merge 4 commits into from

Conversation

zhangysh1995
Copy link

@zhangysh1995 zhangysh1995 commented Sep 15, 2020

What problem does this PR solve?

Issue Number: close #15234

Problem Summary:

  • Invalid zero date could be processed
mysql> select date_add('0000-00-00 00:00:00', interval 2020 year);
+-----------------------------------------------------+
| date_add('0000-00-00 00:00:00', interval 2020 year) |
+-----------------------------------------------------+
| 2019-11-30 00:00:00                                 |
+-----------------------------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> show warnings;
+---------+------+-----------------------------------------+
| Level   | Code | Message                                 |
+---------+------+-----------------------------------------+
| Warning | 1292 | Incorrect time value: '{0 0 0 0 0 0 0}' |
+---------+------+-----------------------------------------+
1 row in set (0.00 sec)

What is changed and how it works?

What's Changed:

  • Return NULL when the first date is invalid

How it Works:

  • Add a invalid check to how related functions
        ...
	if invalidDate := date.InvalidZero(); invalidDate {
		err = handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.TimeStr, date.String()))
		return types.ZeroTime, true, err
	}
        ...
  • Now it becomes:
mysql> select date_add('0000-00-00 00:00:00', interval 2020 year);
+-----------------------------------------------------+
| date_add('0000-00-00 00:00:00', interval 2020 year) |
+-----------------------------------------------------+
| NULL                                                |
+-----------------------------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> show warnings;
+---------+------+----------------------------------------------------+
| Level   | Code | Message                                            |
+---------+------+----------------------------------------------------+
| Warning | 1292 | Incorrect time value: '0000-00-00 00:00:00.000000' |
+---------+------+----------------------------------------------------+
1 row in set (0.00 sec
  • Think a refactor of this patch is necessary, because I use paste now.

Related changes

  • PR to update pingcap/docs/pingcap/docs-cn:

Check List

Tests

  • Unit test

Release note

  • DATE_ADD is compatible with MySQL with handling zero date

@zhangysh1995 zhangysh1995 requested a review from a team as a code owner September 15, 2020 12:38
@zhangysh1995 zhangysh1995 requested review from XuHuaiyu and removed request for a team September 15, 2020 12:38
@ti-srebot ti-srebot added the contribution This PR is from a community contributor. label Sep 15, 2020
@sre-bot
Copy link
Contributor

sre-bot commented Sep 15, 2020

@zhangysh1995
Copy link
Author

/rebuild

@sre-bot
Copy link
Contributor

sre-bot commented Sep 15, 2020

@zhouqiang-cl
Copy link
Contributor

/rebuild

@zhangysh1995
Copy link
Author

@ichn-hu Could you please have a look at the code?

Copy link
Contributor

@rebelice rebelice left a comment

Choose a reason for hiding this comment

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

Could you please add some tests for this PR?

@ichn-hu
Copy link
Contributor

ichn-hu commented Sep 22, 2020

@ichn-hu Could you please have a look at the code?

Sure, sorry for the delay, I don't see any thing wrong, but would you please as @rebelice said add some test which reflects both timestampdiff and date_add returned NULL on the given test case?

@ti-challenge-bot
Copy link

There is no reward for this challenge pull request, so you can request a reward from @XuHuaiyu.

More

Tip : About reward you can refs to reward-command.

Warning: None

@ti-challenge-bot
Copy link

There is no reward for this challenge pull request, so you can request a reward from @XuHuaiyu.

More

Tip : About reward you can refs to reward-command.

Warning: None

@zhangysh1995
Copy link
Author

I found that when the second argument is invalid, TiDB miss an warning:

-- mysql 5.7
mysql> select adddate("2018-08-16 20:21:01", "-00:00:00.000000");
+----------------------------------------------------+
| adddate("2018-08-16 20:21:01", "-00:00:00.000000") |
+----------------------------------------------------+
| 2018-08-16 20:21:01                                |
+----------------------------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> show warnings;
+---------+------+-------------------------------------------------------+
| Level   | Code | Message                                               |
+---------+------+-------------------------------------------------------+
| Warning | 1292 | Truncated incorrect INTEGER value: '-00:00:00.000000' |
+---------+------+-------------------------------------------------------+
1 row in set (0.00 sec)

-- TiDB
mysql> select adddate("2018-08-16 20:21:01", "-00:00:00.000000");
+----------------------------------------------------+
| adddate("2018-08-16 20:21:01", "-00:00:00.000000") |
+----------------------------------------------------+
| 2018-08-16 20:21:01                                |
+----------------------------------------------------+
1 row in set (0.00 sec)

Because this is not related to the current issue, I will not fix it here.

@zhangysh1995 zhangysh1995 reopened this Sep 23, 2020
@ti-challenge-bot
Copy link

There is no reward for this challenge pull request, so you can request a reward from @XuHuaiyu.

More

Tip : About reward you can refs to reward-command.

Warning: None

1 similar comment
@ti-challenge-bot
Copy link

There is no reward for this challenge pull request, so you can request a reward from @XuHuaiyu.

More

Tip : About reward you can refs to reward-command.

Warning: None

@zhangysh1995
Copy link
Author

@XuHuaiyu What would be a possible reward for this issue?

@ti-challenge-bot
Copy link

There is no reward for this challenge pull request, so you can request a reward from @XuHuaiyu.

More

Tip : About reward you can refs to reward-command.

Warning: None

@ti-challenge-bot
Copy link

There is no reward for this challenge pull request, so you can request a reward from @XuHuaiyu.

More

Tip : About reward you can refs to reward-command.

Warning: None

@zhangysh1995
Copy link
Author

zhangysh1995 commented Sep 23, 2020

@rebelice @ichn-hu Added some tests~ Basically, I didn't see a test for date_add so I created a new one.

@zhangysh1995 zhangysh1995 changed the title types: handle zero date in data_add types: handle zero date in date_add Sep 23, 2020
@ti-challenge-bot
Copy link

There is no reward for this challenge pull request, so you can request a reward from @XuHuaiyu.

More

Tip : About reward you can refs to reward-command.

Warning: None

@XuHuaiyu
Copy link
Contributor

/reward 300

@ti-challenge-bot
Copy link

Reward success.

@XuHuaiyu XuHuaiyu added the type/bugfix This PR fixes a bug. label Sep 25, 2020
@@ -3416,6 +3416,11 @@ func (b *builtinAddDateStringStringSig) evalTime(row chunk.Row) (types.Time, boo
return types.ZeroTime, true, err
Copy link
Contributor

Choose a reason for hiding this comment

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

VecEvalTime should also be modified, you can check the following example in MySQL and TiDB

set @@sql_mode='';
create table t(a datetime);
insert into t values('0000-00-00 00:00:00');
select date_add(a, interval 2020 year) from t;

But it'll be ok to fix this in another PR.

Copy link
Author

Choose a reason for hiding this comment

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

@XuHuaiyu @SunRunAway I think this vectorized function should also be fixed, but it may be too many changes for a single PR. To have a cleaner handling of this issue, a refactor of the code may be necessary. For example, I put the valid check in all the add_date functions, but I saw that there is little differences among all the implemented functions. If you think it is better to fix it in the same PR, I will do it. But I will prefer to open a new one for it.

@@ -3449,6 +3454,11 @@ func (b *builtinAddDateStringIntSig) evalTime(row chunk.Row) (types.Time, bool,
return types.ZeroTime, true, err
}

if invalidDate := date.InvalidZero(); invalidDate {
Copy link
Contributor

@SunRunAway SunRunAway Sep 25, 2020

Choose a reason for hiding this comment

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

Is it better to be incorporated into b.getDateFromString?

Copy link
Author

Choose a reason for hiding this comment

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

I think it will help to remove the redundant check in the caller function, but it depends on the context to determine whether zeroDate is valid. For example, adddate('0000-00-00', interval 1 day) is invalid becuase the first zero, while adddate('2000-10-11', 0) is valid with the second argument as a zero. It should be better leave to the caller function, but my current fix is not elegant.

@@ -3449,6 +3454,11 @@ func (b *builtinAddDateStringIntSig) evalTime(row chunk.Row) (types.Time, bool,
return types.ZeroTime, true, err
}

if invalidDate := date.InvalidZero(); invalidDate {
Copy link
Contributor

@SunRunAway SunRunAway Sep 25, 2020

Choose a reason for hiding this comment

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

Should this change be ported into vectorized implementation like builtinAddDateStringIntSig.vecEvalTime? And add more test cases for vectorized situation?

@XuHuaiyu
Copy link
Contributor

I think that handle the vec-cases in another PR is acceptable.

@zz-jason zz-jason changed the title types: handle zero date in date_add expression: handle zero date in date_add() Oct 5, 2020
@ichn-hu ichn-hu mentioned this pull request Nov 3, 2020
@zhangysh1995
Copy link
Author

/pick-up

@ti-challenge-bot
Copy link

It is not a pickable issue!

Details

Tip : If you want this issue to be picked, you need to add a challenge-program label to it.

Warning: None

Copy link
Contributor

@ichn-hu ichn-hu left a comment

Choose a reason for hiding this comment

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

LGTM

@ti-srebot ti-srebot added the status/LGT1 Indicates that a PR has LGTM 1. label Nov 24, 2020
@wshwsh12
Copy link
Contributor

wshwsh12 commented Dec 23, 2020

In master branch 49791bc,

[tidb]> select date_add('0000-00-00 00:00:00', interval 2020 year);
+-----------------------------------------------------+
| date_add('0000-00-00 00:00:00', interval 2020 year) |
+-----------------------------------------------------+
| NULL                                                |
+-----------------------------------------------------+
1 row in set, 1 warning (0.000 sec)

But the following case hasn't fixed.

[tidb]> set @@sql_mode='';
Query OK, 0 rows affected (0.000 sec)

[tidb]> create table t(a datetime);
Query OK, 0 rows affected (0.004 sec)

[tidb]> insert into t values('0000-00-00 00:00:00');
Query OK, 1 row affected (0.003 sec)

[tidb]> select date_add(a, interval 2020 year) from t;
+---------------------------------+
| date_add(a, interval 2020 year) |
+---------------------------------+
| 2019-11-30 00:00:00             |
+---------------------------------+
1 row in set, 1 warning (0.001 sec)

Copy link
Contributor

@wshwsh12 wshwsh12 left a comment

Choose a reason for hiding this comment

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

Why not add error handle in getDateFromXXXXXX ang vecGetDateFromXXXXXX? For your comment, #20015 (comment), I can't get your point.
The second argument will convert to interval, not datetime. So zero value will not cause error..

@zhangysh1995
Copy link
Author

It has been a while since I submitted this PR, I will take a look recently.

@zz-jason
Copy link
Member

@zhangysh1995 any update?

@zhangysh1995
Copy link
Author

@zhangysh1995 any update?

I think a clarification on the scope of this PR is needed. First I want to fix for the non-vectorization case, then the vectorized case is required. Later because the master is fixed, and the latest review requires a refactor of my fix. I think I need a clear goal now for this PR. If a refactor and the additional feature should be fixed, I would consider close this one and open another. @wshwsh12 @XuHuaiyu What are your comments?

@tisonkun
Copy link
Contributor

@zhangysh1995 from @wshwsh12 's comment I think this PR doesn't fix the issue. There are still two unanswered questions:

You can update the PR to fix the specific issue reported in #15234, regardless any further requirement.

@tisonkun tisonkun removed the rewarded label Sep 17, 2021
@ti-chi-bot ti-chi-bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Oct 30, 2021
@ti-chi-bot
Copy link
Member

@zhangysh1995: PR needs rebase.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@zhangysh1995
Copy link
Author

需求变动比较大,现在没精力改这个 PR 了,希望重新 assign 。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component/expression contribution This PR is from a community contributor. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. status/LGT1 Indicates that a PR has LGTM 1. type/bugfix This PR fixes a bug.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

zeroDate behavior for date_add and timestampdiff is not consistent in tidb