[jOOQ/jOOQ#982] Fix spatial bind values in MySQL

MySQL produces an almost WKB style representation from ResultSet, which we can patch to produce the same hex encoded WKB as PostgreSQL. At the same time, we must be able to accept both WKB and WKT content in Spatial::data as bind values, where this makes sense.
This commit is contained in:
Lukas Eder 2021-12-15 11:50:31 +01:00
parent 97c455e748
commit fb2c870bcf
9 changed files with 668 additions and 5 deletions

View File

@ -116,5 +116,6 @@ package org.jooq;

View File

@ -60,5 +60,6 @@ package org.jooq;

View File

@ -21729,6 +21729,104 @@ public class DSL {

View File

@ -122,6 +122,7 @@ import static org.jooq.impl.Keywords.K_TRUE;
import static org.jooq.impl.Keywords.K_YEAR_TO_DAY;
import static org.jooq.impl.Keywords.K_YEAR_TO_FRACTION;
import static org.jooq.impl.Names.N_ST_GEOMFROMTEXT;
import static org.jooq.impl.Names.N_ST_GEOMFROMWKB;
import static org.jooq.impl.R2DBC.isR2dbc;
import static org.jooq.impl.SQLDataType.BIGINT;
import static org.jooq.impl.SQLDataType.BLOB;
@ -138,11 +139,13 @@ import static org.jooq.impl.SQLDataType.ROWID;
import static org.jooq.impl.SQLDataType.SMALLINT;
import static org.jooq.impl.SQLDataType.TIME;
import static org.jooq.impl.SQLDataType.TIMESTAMP;
import static org.jooq.impl.SQLDataType.VARBINARY;
import static org.jooq.impl.SQLDataType.VARCHAR;
import static org.jooq.impl.Tools.apply;
import static org.jooq.impl.Tools.asInt;
import static org.jooq.impl.Tools.attachRecords;
import static org.jooq.impl.Tools.convertBytesToHex;
import static org.jooq.impl.Tools.convertHexToBytes;
import static org.jooq.impl.Tools.emulateMultiset;
import static org.jooq.impl.Tools.enums;
// ...
@ -165,6 +168,7 @@ import java.io.StringReader;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.sql.Array;
import java.sql.Blob;
import java.sql.Clob;
@ -199,6 +203,7 @@ import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.regex.Pattern;
// ...
import org.jooq.Attachable;
@ -234,6 +239,7 @@ import org.jooq.RowId;
import org.jooq.SQLDialect;
import org.jooq.Schema;
import org.jooq.Scope;
// ...
import org.jooq.TableRecord;
import org.jooq.UDT;
import org.jooq.UDTField;
@ -5025,6 +5031,95 @@ public class DefaultBinding<T, U> implements Binding<T, U> {

View File

@ -428,6 +428,7 @@ final class Names {
static final Name N_STDDEV_POP = unquotedName("stddev_pop");
static final Name N_STDDEV_SAMP = unquotedName("stddev_samp");
static final Name N_ST_AREA = unquotedName("st_area");
static final Name N_ST_ASBINARY = unquotedName("st_asbinary");
static final Name N_ST_ASTEXT = unquotedName("st_astext");
static final Name N_ST_CENTROID = unquotedName("st_centroid");
static final Name N_ST_CONTAINS = unquotedName("st_contains");
@ -441,6 +442,7 @@ final class Names {
static final Name N_ST_GEOMETRYN = unquotedName("st_geometryn");
static final Name N_ST_GEOMETRYTYPE = unquotedName("st_geometrytype");
static final Name N_ST_GEOMFROMTEXT = unquotedName("st_geomfromtext");
static final Name N_ST_GEOMFROMWKB = unquotedName("st_geomfromwkb");
static final Name N_ST_INTERIORRINGN = unquotedName("st_interiorringn");
static final Name N_ST_INTERSECTION = unquotedName("st_intersection");
static final Name N_ST_INTERSECTS = unquotedName("st_intersects");

View File

@ -5534,6 +5534,40 @@ public final class QOM {

View File

@ -0,0 +1,177 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;

View File

@ -0,0 +1,207 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;

View File

@ -938,7 +938,16 @@ final class Tools {
* All hexadecimal digits accessible through array index, e.g.
* <code>HEX_DIGITS[15] == 'f'</code>.
*/
private static final char[] HEX_DIGITS = "0123456789abcdef".toCharArray();
private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray();
private static final byte[] HEX_LOOKUP = {
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x30 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
/* 0x40 */ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x60 */ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
static final Set<SQLDialect> REQUIRES_BACKSLASH_ESCAPING = SQLDialect.supportedBy(MARIADB, MYSQL);
static final Set<SQLDialect> NO_SUPPORT_NULL = SQLDialect.supportedBy(DERBY, FIREBIRD, HSQLDB);
@ -5858,14 +5867,17 @@ final class Tools {
* @param len the number of bytes to encode
* @return the hex encoded string
*/
static final String convertBytesToHex(byte[] value, int len) {
char[] buff = new char[len + len];
static final String convertBytesToHex(byte[] value, int offset, int len) {
len = Math.min(value.length - offset, len);
char[] buff = new char[2 * len];
char[] hex = HEX_DIGITS;
for (int i = 0; i < len; i++) {
int c = value[i] & 0xff;
int c = value[i + offset] & 0xff;
buff[i + i] = hex[c >> 4];
buff[i + i + 1] = hex[c & 0xf];
}
return new String(buff);
}
@ -5876,7 +5888,43 @@ final class Tools {
* @return the hex encoded string
*/
static final String convertBytesToHex(byte[] value) {
return convertBytesToHex(value, value.length);
return convertBytesToHex(value, 0, value.length);
}
/**
* Convert a hex encoded string to a byte array.
*
* @param value the hex encoded string
* @param len the number of bytes to encode
* @return the byte array
*/
static final byte[] convertHexToBytes(String value, int offset, int len) {
len = Math.min(value.length() / 2 - offset, len);
byte[] buff = new byte[len];
byte[] lookup = HEX_LOOKUP;
int max = lookup.length;
for (int i = 0; i < len; i++) {
int pos = (i + offset) * 2;
char c1 = value.charAt(pos);
char c2 = value.charAt(pos + 1);
byte v1 = c1 < max ? lookup[c1] : 0;
byte v2 = c2 < max ? lookup[c2] : 0;
buff[i] = (byte) ((v1 << 4) + v2);
}
return buff;
}
/**
* Convert a hex encoded string to a byte array.
*
* @param value the hex encoded string
* @return the byte array
*/
static final byte[] convertHexToBytes(String value) {
return convertHexToBytes(value, 0, value.length());
}
static final boolean isNotEmpty(Collection<?> collection) {