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

*: add builtin function TIMESTAMPDIFF #2386

Merged
merged 10 commits into from
Jan 10, 2017
Merged

Conversation

tiancaiamao
Copy link
Contributor

For issue #236

sc := ctx.GetSessionVars().StmtCtx
t1, err := convertDatumToTime(sc, args[1])
if err != nil {
return
Copy link
Member

Choose a reason for hiding this comment

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

return d, errors.Trace(err)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No need, timestampdiff return NULL for illegal input.

mysql> select timestampdiff(MONTH, 'asdlfjasdf', '2017-01-01');
+--------------------------------------------------+
| timestampdiff(MONTH, 'asdlfjasdf', '2017-01-01') |
+--------------------------------------------------+
|                                             NULL |
+--------------------------------------------------+
1 row in set, 1 warning (0.00 sec)

Copy link
Member

Choose a reason for hiding this comment

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

May be it depends on sql_mode and statement type? Please try to insert timestampdiff(MONTH, 'asdlfjasdf', '2017-01-01') into some table.

}
t2, err := convertDatumToTime(sc, args[2])
if err != nil {
return
Copy link
Member

Choose a reason for hiding this comment

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

return d, errors.Trace(err)

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

}
if t1.Time.Month() == 0 || t1.Time.Day() == 0 ||
t2.Time.Month() == 0 || t2.Time.Day() == 0 {
return
Copy link
Member

Choose a reason for hiding this comment

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

Add a test case for this. MySQL perform in the same way?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

MySQL return NULL if month or day contains 0
Here is test case
https://github.com/pingcap/tidb/pull/2386/files#diff-9efa9861dfe0962aeeda87c63deb0f0fR559

Copy link
Member

Choose a reason for hiding this comment

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

ok

Conflicts:
	expression/builtin_time_test.go
	plan/typeinferer_test.go
@zimulala
Copy link
Contributor

zimulala commented Jan 5, 2017

@tiancaiamao Fix conflicts.

Conflicts:
	expression/builtin.go
	expression/builtin_time.go
	expression/builtin_time_test.go
	plan/typeinferer_test.go
dayBeg = uint(t1.Day())
dayEnd = uint(t2.Day())
secondBeg = uint(t1.Hour()*3600 + t1.Minute()*60 + t1.Second())
secondEnd = uint(t2.Hour()*3600 + t2.Minute()*60 + t2.Second())
Copy link
Member

Choose a reason for hiding this comment

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

Can you add a function called totalSeconds to do this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hour * 3600 + minute * 60 + second is intuitive, totalSeconds doesn't make it better.

case intervalDAY:
return int64(seconds) / secondsIn24Hour * negV
case intervalHOUR:
return int64(seconds) / 3600 * negV
Copy link
Member

Choose a reason for hiding this comment

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

Why not add a const called secondsInOneHour and secondsInOneMinute

Copy link
Contributor Author

Choose a reason for hiding this comment

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

because 3600 is intuitive enough, and mysql also do that.

// in microseconds fits into longlong.
return int64(seconds*1000000+microseconds) * negV
default:
break
Copy link
Member

Choose a reason for hiding this comment

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

This line can be removed ?

}

// errorOrWarning reports error or warning depend on the context.
func errorOrWarning(err error, ctx context.Context) error {
Copy link
Member

Choose a reason for hiding this comment

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

Will this function be used in other place ? It's better to move it to util.go ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No other place use it currently, and we don't fully support warning now.
Maybe it would be use in the future, but we can refact then.

Copy link
Member

Choose a reason for hiding this comment

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

Use StmtCtx instead of Context is better.

if err != nil {
return d, errorOrWarning(err, ctx)
}
if t1.Time.Month() == 0 || t1.Time.Day() == 0 || t2.Time.Month() == 0 || t2.Time.Day() == 0 {
Copy link
Member

Choose a reason for hiding this comment

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

Do we need a function Time.Invalid() ?

@hanfei1991
Copy link
Member

LGTM

// TimestampDiff returns t2 - t1 where t1 and t2 are date or datetime expressions.
// The unit for the result (an integer) is given by the unit argument.
// The legal values for unit are "YEAR" "QUARTER" "MONTH" "DAY" "HOUR" "SECOND" and so on.
func TimestampDiff(unit string, t1 Time, t2 Time) int64 {
Copy link
Member

Choose a reason for hiding this comment

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

Why we need this function?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because timestampDiff in mytime.go is not exported, expression package need use it.

I keep most mysql time function in mytime.go and keep them internal, while expose some of the for outside usage.

}

// errorOrWarning reports error or warning depend on the context.
func errorOrWarning(err error, ctx context.Context) error {
Copy link
Member

Choose a reason for hiding this comment

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

Use StmtCtx instead of Context is better.

@shenli
Copy link
Member

shenli commented Jan 7, 2017

@tiancaiamao Please fix the conflict.

Conflicts:
	expression/builtin_time.go
@tiancaiamao
Copy link
Contributor Author

PTAL @shenli

@shenli
Copy link
Member

shenli commented Jan 10, 2017

LGTM
We should discus this later.

@tiancaiamao tiancaiamao merged commit 5969e9e into master Jan 10, 2017
@tiancaiamao tiancaiamao deleted the tiancaiamao/timestamp-diff branch January 10, 2017 16:12
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.

4 participants