[MDEV-15429] CONNECT engine JDBC handling Postgresql UUID type Created: 2018-02-27 Updated: 2018-04-26 Resolved: 2018-03-12 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Storage Engine - Connect |
| Fix Version/s: | 10.0.35, 10.1.32, 10.2.14 |
| Type: | Task | Priority: | Major |
| Reporter: | Robert Dyas | Assignee: | Olivier Bertrand |
| Resolution: | Done | Votes: | 0 |
| Labels: | None | ||
| Description |
|
Using CONNECT JDBC with a Postgres database that has UUID seems impossible right now. I've tried mapping them to VARCHAR(36) and BINARY(16) but can't seem to get any valid data back. The JDBC driver sees this a type OTHER data_type number 1111. Any ideas? Unfortunately we have a customer where the entire DB is setup around UUIDs. |
| Comments |
| Comment by Olivier Bertrand [ 2018-03-05 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Good, if you're sure that the returned type is 1111 I can add it to the translate table. I think it would be CHAR(36) as UUID have always the same size. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Robert Dyas [ 2018-03-05 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Yes, when I manually map to char(36) it comes back blank. I haven't had a chance to build an external use case, but it might possibly be an issue if select of uuid is via prepared statement. I have submitted a case on their driver, but if you have a test env already, maybe it's something connect specific? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Olivier Bertrand [ 2018-03-07 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Indeed, and I am working on it. I already can automatically specify UUID columns as CHAR(36) when using discovery and read such columns; remains to handle the write operations. However, as you have customer having tables of UUID type, let's see what can be done waiting to this issue fix. Discovery fails and manually declaring the column as CHAR(36) does work either. The reason why is that the UUID data type is specific to PostgreSQL but is not a SQL type nor a JDBC type. Therefore, these columns cannot be handled and must be removed from the CONNECT jdbc table. When using discovery, this is done by executing:
It is Ok if these columns are not used in current operations. However, it may be necessary to handle them. Let us suppose a PostgreSQL table was created by:
For write operations, this can be done externally to MariaDB using psql or pgAdmin, but also from MariaDB by creating a table allowing to execute SQL statements. For instance:
Then you can have PostgreSQL execute a command using PostgreSQL syntax, for instance:
This replies for instance:
However, to query such a table, you must force PostgreSQL to return the string representation of the UUID column. This can be done by creating a table specifying the PostgreSQL query using the SRCDEF option. For instance:
Then
replies:
This oblige to create a table for each query or use the same one altered by ALTER TABLE. I tried to automate it with a procedure but unsuccessfully. Note: In the last CREATE TABLE discovery cannot be used and the columns must be defined explicitly because PosgreSQL returns a type of VARCHAR(2147483647), which is invalid for MariaDB. Unfortunately these column definitions must be updated to mach the SRCDEF query result set. Hope a fix will be available soon. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Robert Dyas [ 2018-03-07 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I think this shouldn't be this hard. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Robert Dyas [ 2018-03-07 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Here is the link to my issue on the Postgresql jdbc driver uuid problem: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Olivier Bertrand [ 2018-03-07 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Indeed, getString doesn't work (it returns a null string). But I could make it to work by getObject().toString. However it is more complex in the other way. PostgreSQL does not accept a String to create a UUID. I'll try the way indicated in: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Robert Dyas [ 2018-03-07 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I think if you post on the link above, they intend that getString() should simply return char36 and you should simply be able to setString as a char to set it - anything else is a driver bug in my view. If you post, they will fix it I think. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Olivier Bertrand [ 2018-03-08 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I can confirm that using the PostgreSQL JDBC driver 42.2.1 getString returns null for a UUID column and that trying to set it by setString fails with a message saying something like:
(translated from French) This is bad because, even it is easy to get the UUID value by getObject and toString and to set it by setObject of a UUID Java object, it requires CONNECT to be updated. Indeed, when reading, the remote column type can be retrieved and when it is 1111 a special function must be called. However, the local column type being CHAR(36) or VARCHAR(36), CONNECT has to get the type of the remote column to know if it must call a specialized function. This is not trivial and could be avoided if the JDBC driver was fixed. Perhaps you should report this on the PostgreSQL JDBC driver site so this could be fixed. If so, just specying the column as CHAR(36) or VARCHAR(36) will work, even with older MariaDB version (just discovery won't, unless SKIP is specified) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Robert Dyas [ 2018-03-08 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Can you please post that to the thread listed above for postgres jdbc driver bugs? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Robert Dyas [ 2018-03-10 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Well, I tried simply declaring the UUID as char(36) or varchar(36) and then setting the postgresl url parameter to stringType=unspecified but I am still getting blank UUIDs and no error message. I would be happy at this stage if CONNECT could read uuid if I manually specify them as char(36) or varchar(36). Is this reasonable without a driver change, or is it too cumbersome? If I understood their last post correctly, it seems like connect would need no change to read a UUID column...so I guess I don't understnd. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Olivier Bertrand [ 2018-03-10 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Strangely enough, when I call the same JDBCInterface functions from a Java test client, at least reading UUID with getString works allright. But when the same functions is called from CONNECT via JNI, it returns a null string. Anyhow, I have made a fix in CONNECT that I will publish by the time I thoroughly test it. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Olivier Bertrand [ 2018-03-12 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
UUID will be translated to CHAR(36) when column definitions are set using discovery. Locally a PostgreSQL UUID column will be handled like a CHAR or VARCHAR column. Example: Using the PostgreSQL table testuuid in the text database:
Its column definitions can by queried by:
This returns:
Note: PostgreSQL, when a column size is undefined, returns 2147483647, which is not acceptable for MariaDB. CONNECT change it to the value of the connect_conv_size session variable. Also, for TEXT columns the data type returned is 12 (SQL_VARCHAR) instead of -1 the SQL_TEXT value. Accessing this table via JDBC by:
it will be created as:
Note: 8192 being here the connect_conv_size value.
Here the id column values come from the DEFAULT of the PostgreSQL column that was specified as uuid_generate_v4().
The first insert specifies a valid UUID character representation. The second one set it to NULL. The third one (a void string) generates a Java random UUID. These commands both work:
However, this one fails:
Saying:
This because CONNECT cond_push feature added the WHERE clause to the query sent to PostgreSQL:
and the LIKE operator does not apply to UUID in PostgreSQL.
Doing so, the where clause will be executed by MariaDB only and the query will not fail anymore. |