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

sql: add types, datum and encoding for TimeTZ #42481

Merged
merged 1 commit into from
Nov 20, 2019

Conversation

otan
Copy link
Contributor

@otan otan commented Nov 14, 2019

Refs: #26097

This PR adds the types to the type system to support TimeTZ, adding the
tree.Datum class to ensure it can be parsed and then also adds the
encoding for TimeTZ to be put in the database. This is the minimum
amount of work needed before any set of tests can pass - trying to keep
the PRs small but in the end did not succeed.

Changes per package (and recommended review order) are as follows:

sql/types: added the new TimeTZ type and type family.

pkg/util/timetz: introduce new TimeTZ type

Added a custom wrapper around timeofday and offset seconds, which form
follows postgres' implementation of TimeTzADT. Note that OffsetSecs
being negative / not what you expect is fully handled by all utility
functions from this interface.

pkg/sql/sem/tree: add Datum for DTimeTZ

A wrapper around TimeTZ for the tree expressions.
Also removed some magic constants I found whilst form following other
things.

pkg/util/timeutil/pgdate: remove usage of testutil.IsError

This causes a circular dependency on the new timetz type, and this was a
very straightforward way of going around it.

pkg/util/encoding: added encoding for DTimeTZ
Form following postgres, we store the timeofday and offset into the
database as 12 bytes - an 8 and 4 byte varint. To have sort order right,
and to form follow the btree encoding for TimeTZ, we use UTC time when
storing it for (En|De)codeTimeTZ[As|Des]cending.

pkg/sql/pgwire: added pgwire for DTimeTZ

pkg/sql/sqlbase: added necessary changes to encode TimeTZ data

ccl/changefeedccl: added encoding for ccl
Note we must use the string type here as we cannot encode two ints
nicely with avro, nor is one int enough to not lose data.

sql/parser: added parsing support for TimeTZ
I wanted to omit this in this PR but some of the automated tests
iterating over every time needs this. Note there are more bits to
implement which I will leave for a later PR.

pkg/cli: add ability to dump TimeTZ

sql/logictest/testdata/logic_test: added basic tests for TimeTZ
More to come, but here are some now since the parser is all hooked up.

As this is not the fully featured commit yet, I am omitting the release
note until the test suite is more fleshed out.

Release note: none

@otan otan requested review from solongordon and a team November 14, 2019 15:23
@otan otan requested review from a team as code owners November 14, 2019 15:23
@cockroach-teamcity
Copy link
Member

This change is Reviewable

@knz
Copy link
Contributor

knz commented Nov 14, 2019

I haven't reviewed yet (and I'll let Solon do the first pass anyway) but I'd like to commend you on the elaborate commit message.

Also you probably want to refer to #26097 in the PR description.

Copy link
Contributor

@solongordon solongordon left a comment

Choose a reason for hiding this comment

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

Looks great in general! I left some mostly minor thoughts.

Reviewed 51 of 51 files at r1.
Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @otan)


pkg/sql/logictest/testdata/logic_test/timetz, line 15 at r1 (raw file):

# structure underneath should still be correct.
query B
SELECT '24:00:00-1459' > '23:59:59-1459';

Looks like you're just comparing strings here, not TIMETZs. Better to do SELECT '24:00:00-1459':::TIMETZ > '23:59:59-1459':::TIMETZ or SELECT b > '23:59:59-1459' FROM timetz_test WHERE c = 4.

Also note that if it makes things less confusing, you can cast to string when you select from timetz_test in the queries below.


pkg/sql/sem/tree/datum.go, line 1958 at r1 (raw file):

var (
	dMaxTimeTZOffsetSecs = int32((14*time.Hour + 59*time.Minute) / time.Second)

This value is mysterious to me. Add a comment?

Also, just from fooling around in a Postgres shell it seems like maybe 15:59 is the max it accepts, not 14:59?

Also it doesn't look like you currently prevent storing a larger offset than this. Though maybe you're planning to handle that in follow-up parsing work?


pkg/sql/sem/tree/datum_invariants_test.go, line 62 at r1 (raw file):

			desc:     "same DTimeTZ are equal",
			left:     NewDTimeTZFromOffset(timeofday.New(22, 0, 0, 0), sydneyTimeZone),
			right:    NewDTimeTZFromOffset(timeofday.New(22, 0, 0, 0), sydneyTimeZone),

🇦🇺


pkg/sql/types/types.go, line 255 at r1 (raw file):

	// For example:
	//
	//   HH:MM:SS.sssss+-ZZ:ZZ

🔎 Is there an s missing?


pkg/util/encoding/encoding.go, line 955 at r1 (raw file):

func EncodeTimeTZAscending(b []byte, t timetz.TimeTZ) []byte {
	// Do not use TimeOfDay's add function, as it loses 24:00:00 encoding.
	return encodeTimeTZ(b, int64(t.TimeOfDay)+int64(t.OffsetSecs)*1000000, t.OffsetSecs)

Nit: Would be nice to make 1000000 a named constant.


pkg/util/encoding/encoding_test.go, line 1288 at r1 (raw file):

	return timetz.MakeTimeTZ(
		timeofday.FromInt(rd.Int63n(int64(timeofday.Max))),
		rd.Int31n(28*60*60)-14*60*60,

Minor: Seems like this doesn't quite cover the max and min values.


pkg/util/timetz/timetz.go, line 27 at r1 (raw file):

var (
	// TimeTZMaxTimeRegex is a compiled regex for parsing the 24:00 timetz value
	TimeTZMaxTimeRegex = regexp.MustCompile(`^24:00((:00)|(:00.0+))?([+-](([\d]+)|(\d{1,2}(:\d{1,2}){0,2})))?$`)

I'm probably missing something but seems like this regex could just be ^24 without any loss of functionality.


pkg/util/timetz/timetz.go, line 116 at r1 (raw file):

	}
	// time.Format does not work for negative zone offsets
	// which are in seconds less than 60.

wat

Copy link
Contributor Author

@otan otan left a comment

Choose a reason for hiding this comment

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

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @solongordon)


pkg/sql/logictest/testdata/logic_test/timetz, line 15 at r1 (raw file):

Previously, solongordon (Solon) wrote…

Looks like you're just comparing strings here, not TIMETZs. Better to do SELECT '24:00:00-1459':::TIMETZ > '23:59:59-1459':::TIMETZ or SELECT b > '23:59:59-1459' FROM timetz_test WHERE c = 4.

Also note that if it makes things less confusing, you can cast to string when you select from timetz_test in the queries below.

Done. Handy tip too - also converted to string casts!


pkg/sql/sem/tree/datum.go, line 1958 at r1 (raw file):

Previously, solongordon (Solon) wrote…

This value is mysterious to me. Add a comment?

Also, just from fooling around in a Postgres shell it seems like maybe 15:59 is the max it accepts, not 14:59?

Also it doesn't look like you currently prevent storing a larger offset than this. Though maybe you're planning to handle that in follow-up parsing work?

I was following https://www.postgresql.org/docs/current/datatype-datetime.html for 14:59 -- guess we might as well do 15:59!

I will add a comment, and made sure the parser corrects for this.


pkg/sql/types/types.go, line 255 at r1 (raw file):

Previously, solongordon (Solon) wrote…

🔎 Is there an s missing?

Done. Nice catch, hah!


pkg/util/timetz/timetz.go, line 27 at r1 (raw file):

Previously, solongordon (Solon) wrote…

I'm probably missing something but seems like this regex could just be ^24 without any loss of functionality.

Done.


pkg/util/timetz/timetz.go, line 116 at r1 (raw file):

Previously, solongordon (Solon) wrote…

wat

Yep - clarified with a command.

Copy link
Contributor

@solongordon solongordon left a comment

Choose a reason for hiding this comment

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

:lgtm:

Reviewable status: :shipit: complete! 1 of 0 LGTMs obtained (waiting on @solongordon)

@solongordon
Copy link
Contributor

FYI it looks like one of the benchmarks is failing. You can reproduce like this:

make bench PKG=./pkg/util/encoding BENCHES=BenchmarkDecodeTimeTZValue

This PR adds the types and framework to support TimeTZ, adding the
tree.Datum class to ensure it can be parsed and then also adds the
encoding for TimeTZ to be put in the database. This is the minimum
amount of work needed before any set of tests can pass - trying to keep
the PRs small but in the end did not succeed due to automated tests
iterating over all the types.

Changes per package (and recommended review order) are as follows:

**sql/types: added the new TimeTZ type and type family.**

**pkg/util/timetz: introduce new TimeTZ type**

Added a custom wrapper around timeofday and offset seconds, which form
follows postgres' implementation of `TimeTzADT`. Note that `OffsetSecs`
being negative / not what you expect is fully handled by all utility
functions from this interface.

**pkg/sql/sem/tree: add Datum for DTimeTZ**

A wrapper around TimeTZ for the tree expressions.
Also removed some magic constants I found whilst form following other
things.

**pkg/util/timeutil/pgdate: remove usage of testutil.IsError**

This causes a circular dependency on the new timetz type, and this was a
very straightforward way of going around it.

**pkg/util/encoding: added encoding for DTimeTZ**
Form following postgres, we store the timeofday and offset into the
database as 12 bytes - an 8 and 4 byte varint. To have sort order right,
and to form follow the btree encoding for TimeTZ, we use UTC time when
storing it for `(En|De)codeTimeTZ[As|Des]cending`.

**pkg/sql/pgwire: added pgwire for DTimeTZ**

**pkg/sql/sqlbase: added necessary changes to encode TimeTZ data**

**ccl/changefeedccl: added encoding for ccl**
Note we must use the string type here as we cannot encode two ints
nicely with avro, nor is one int enough to not lose data.

**sql/parser: added parsing support for TimeTZ**
I wanted to omit this in this PR but some of the automated tests
iterating over every time needs this. Note there are more bits to
implement which I will leave for a later PR.

**pkg/cli: add ability to dump TimeTZ**

**builtins: added equality support for TimeTZ**

**sql/logictest/testdata/logic_test: added basic tests for TimeTZ**
More to come, but here are some now since the parser is all hooked up.

As this is not the fully featured commit yet, I am omitting the release
note until the test suite is more fleshed out.

Release note: none
@otan
Copy link
Contributor Author

otan commented Nov 19, 2019

Yeah, I thought it was a flake because make bench always flakes. Fixed it!

@knz did you want to review this, or can I push ahead?

@otan
Copy link
Contributor Author

otan commented Nov 20, 2019

bors r=solongordon

i'm going to land this, i will respond to subsequent comments later - want to progress on this!

craig bot pushed a commit that referenced this pull request Nov 20, 2019
42481: sql: add types, datum and encoding for TimeTZ r=solongordon a=otan

Refs: #26097

This PR adds the types to the type system to support TimeTZ, adding the
tree.Datum class to ensure it can be parsed and then also adds the
encoding for TimeTZ to be put in the database. This is the minimum
amount of work needed before any set of tests can pass - trying to keep
the PRs small but in the end did not succeed.

Changes per package (and recommended review order) are as follows:

**sql/types: added the new TimeTZ type and type family.**

**pkg/util/timetz: introduce new TimeTZ type**

Added a custom wrapper around timeofday and offset seconds, which form
follows postgres' implementation of `TimeTzADT`. Note that `OffsetSecs`
being negative / not what you expect is fully handled by all utility
functions from this interface.

**pkg/sql/sem/tree: add Datum for DTimeTZ**

A wrapper around TimeTZ for the tree expressions.
Also removed some magic constants I found whilst form following other
things.

**pkg/util/timeutil/pgdate: remove usage of testutil.IsError**

This causes a circular dependency on the new timetz type, and this was a
very straightforward way of going around it.

**pkg/util/encoding: added encoding for DTimeTZ**
Form following postgres, we store the timeofday and offset into the
database as 12 bytes - an 8 and 4 byte varint. To have sort order right,
and to form follow the btree encoding for TimeTZ, we use UTC time when
storing it for `(En|De)codeTimeTZ[As|Des]cending`.

**pkg/sql/pgwire: added pgwire for DTimeTZ**

**pkg/sql/sqlbase: added necessary changes to encode TimeTZ data**

**ccl/changefeedccl: added encoding for ccl**
Note we must use the string type here as we cannot encode two ints
nicely with avro, nor is one int enough to not lose data.

**sql/parser: added parsing support for TimeTZ**
I wanted to omit this in this PR but some of the automated tests
iterating over every time needs this. Note there are more bits to
implement which I will leave for a later PR.

**pkg/cli: add ability to dump TimeTZ**

**sql/logictest/testdata/logic_test: added basic tests for TimeTZ**
More to come, but here are some now since the parser is all hooked up.

As this is not the fully featured commit yet, I am omitting the release
note until the test suite is more fleshed out.

Release note: none

Co-authored-by: Oliver Tan <otan@cockroachlabs.com>
Copy link
Contributor

@knz knz left a comment

Choose a reason for hiding this comment

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

I can't review this properly anytime soon. I'll trust Solon on the code review, but please approach mjibson to do throrough random checks including comparison with pg.

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (and 1 stale) (waiting on @solongordon)

@craig
Copy link
Contributor

craig bot commented Nov 20, 2019

Build succeeded

@craig craig bot merged commit 8bfdcea into cockroachdb:master Nov 20, 2019
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