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

Fix failure of insertion of timestamp on JDBC #8201

Closed
wants to merge 1 commit into from
Closed

Fix failure of insertion of timestamp on JDBC #8201

wants to merge 1 commit into from

Conversation

ShanBai6
Copy link

@ShanBai6 ShanBai6 commented Jun 6, 2017

Fix the timestamp issue #7747 and Add/Extend original test to cover the timestamp type as well.

@facebook-github-bot
Copy link
Collaborator

Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file. In order for us to review and merge your code, please sign up at https://code.facebook.com/cla - and if you have received this in error or have any questions, please drop us a line at cla@fb.com. Thanks!

If you are contributing on behalf of someone else (eg your employer): the individual CLA is not sufficient - use https://developers.facebook.com/opensource/cla?type=company instead. Contact cla@fb.com if you have any questions.

@@ -130,6 +132,11 @@ public void appendLong(long value)
long localMillis = ISOChronology.getInstanceUTC().getZone().getMillisKeepLocal(DateTimeZone.getDefault(), utcMillis);
statement.setDate(next(), new Date(localMillis));
}
else if (TIMESTAMP.equals(columnTypes.get(field))) {
long utcMillis = TimeUnit.MILLISECONDS.toMillis(value);
Copy link
Member

Choose a reason for hiding this comment

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

It does nothing

/**
     * Time unit representing one thousandth of a second
     */
    MILLISECONDS {
        public long toNanos(long d)   { return x(d, C2/C0, MAX/(C2/C0)); }
        public long toMicros(long d)  { return x(d, C2/C1, MAX/(C2/C1)); }
        public long toMillis(long d)  { return d; }
        public long toSeconds(long d) { return d/(C3/C2); }
        public long toMinutes(long d) { return d/(C4/C2); }
        public long toHours(long d)   { return d/(C5/C2); }
        public long toDays(long d)    { return d/(C6/C2); }
        public long convert(long d, TimeUnit u) { return u.toMillis(d); }
        int excessNanos(long d, long m) { return 0; }
    },

Copy link
Contributor

Choose a reason for hiding this comment

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

Has this been addressed?

Copy link
Author

Choose a reason for hiding this comment

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

This is the same portion of code as below, we decide to keep it as this for now.

else if (TIMESTAMP.equals(columnTypes.get(field))) {
long utcMillis = TimeUnit.MILLISECONDS.toMillis(value);
long localMillis = ISOChronology.getInstanceUTC().getZone().getMillisKeepLocal(DateTimeZone.getDefault(), utcMillis);
statement.setTimestamp(next(), new Timestamp(localMillis));
Copy link
Member

Choose a reason for hiding this comment

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

try to use the following method

statement.setTimestamp(next(), new Timestamp(utcMillis), Calendar.getInstance(/*force time zone to be UTC*/TimeZone.getTimeZone("UTC"), /*force calendar to be Gregorian*/ ENGLISH);)

Copy link
Contributor

Choose a reason for hiding this comment

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

AFAIK, postgres doesn't follow standard with respect to timestamp semantics. Did you check that?
In anyway, make sure value read from postgres is the same as value written earlier.

Copy link
Author

@ShanBai6 ShanBai6 Jun 6, 2017

Choose a reason for hiding this comment

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

This will be done in a separate patch after further discussion.

MaterializedResult actualColumns = computeActual("DESC ORDERS").toJdbcTypes();

// some connectors don't support dates, and some do not support parametrized varchars, so we check multiple options
execute("CREATE TABLE tpch.test (test_bigint bigint, test_varchar varchar(255), test_vardiff varchar(15), test_double double, test_date date, test_integer integer, test_timestamp timestamp)");
Copy link
Member

Choose a reason for hiding this comment

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

Name test is too generic. Call it test_describe_table_all_types.

MaterializedResult actualColumns = computeActual("DESC ORDERS").toJdbcTypes();

// some connectors don't support dates, and some do not support parametrized varchars, so we check multiple options
execute("CREATE TABLE tpch.test (test_bigint bigint, test_varchar varchar(255), test_vardiff varchar(15), test_double double, test_date date, test_integer integer, test_timestamp timestamp)");
Copy link
Member

Choose a reason for hiding this comment

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

Prefix column names with c_ instead of test_. For instance c_varchar_255, c_varchar_15, c_timestamp, etc.

execute("CREATE TABLE tpch.test_insert (x bigint, y varchar(100))");
assertUpdate("INSERT INTO test_insert VALUES (123, 'test')", 1);
assertQuery("SELECT * FROM test_insert", "SELECT 123 x, 'test' y");
execute("CREATE TABLE tpch.test_insert (x bigint, y varchar(100), t_ts timestamp)");
Copy link
Member

Choose a reason for hiding this comment

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

Do "all types" test as it is done for describe statement.

Copy link
Author

Choose a reason for hiding this comment

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

Describe test could be done for all types, while the insertion has to wait for later as some data types still have issues.

execute("CREATE TABLE tpch.test_insert (x bigint, y varchar(100))");
assertUpdate("INSERT INTO test_insert VALUES (123, 'test')", 1);
assertQuery("SELECT * FROM test_insert", "SELECT 123 x, 'test' y");
execute("CREATE TABLE tpch.test_insert (x bigint, y varchar(100), t_ts timestamp)");
Copy link
Member

Choose a reason for hiding this comment

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

Same comment about column names

public void testDescribeTable()
throws Exception
{
execute("CREATE TABLE tpch.test (test_timestamp timestamp without time zone, test_timestamp_tz timestamp with time zone)");
Copy link
Member

Choose a reason for hiding this comment

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

ditto

execute("CREATE TABLE tpch.test_insert (x bigint, y varchar(100))");
assertUpdate("INSERT INTO test_insert VALUES (123, 'test')", 1);
assertQuery("SELECT * FROM test_insert", "SELECT 123 x, 'test' y");
execute("CREATE TABLE tpch.test_insert (x bigint, y varchar, t_ts timestamp)");
Copy link
Member

Choose a reason for hiding this comment

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

ditto

else if (TIMESTAMP.equals(columnTypes.get(field))) {
long utcMillis = TimeUnit.MILLISECONDS.toMillis(value);
long localMillis = ISOChronology.getInstanceUTC().getZone().getMillisKeepLocal(DateTimeZone.getDefault(), utcMillis);
statement.setTimestamp(next(), new Timestamp(localMillis));
Copy link
Contributor

Choose a reason for hiding this comment

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

AFAIK, postgres doesn't follow standard with respect to timestamp semantics. Did you check that?
In anyway, make sure value read from postgres is the same as value written earlier.

execute("CREATE TABLE tpch.test_insert (x bigint, y varchar(100))");
assertUpdate("INSERT INTO test_insert VALUES (123, 'test')", 1);
assertQuery("SELECT * FROM test_insert", "SELECT 123 x, 'test' y");
execute("CREATE TABLE tpch.test_insert (x bigint, y varchar, t_ts timestamp)");
Copy link
Contributor

Choose a reason for hiding this comment

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

None of the tests exercises CTAS and #7747 mentions CTAS.

@arhimondr
Copy link
Member

LGTM

@kubum
Copy link

kubum commented Jan 9, 2019

Hi @arhimondr! It looks like an interesting PR, if I fix the conflicts would you be able to help and a look again into merging it? Thanks!

@findepi
Copy link
Contributor

findepi commented Jan 9, 2019

There is no correct and portable way for handling timestamps, especially when legacy_timestamp=false session toggle is set.
@kubum #12151 is a refactor that provides basis for handling the conversions in database-specific way where appropriate.

@findepi findepi closed this Jan 9, 2019
@kubum
Copy link

kubum commented Jan 9, 2019

Thank you for the quick response @findepi!

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.

5 participants