Skip to content

Commit

Permalink
Merge branch 'develop' into bugfix_placeholder_in_joincondition_notco…
Browse files Browse the repository at this point in the history
…nsidered
  • Loading branch information
renliangyu857 committed Nov 14, 2022
2 parents 4ee18b4 + 42f0446 commit 27ad395
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 15 deletions.
2 changes: 2 additions & 0 deletions changes/en-us/develop.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ Add changes here for all PR submitted to the develop branch.
- [[#4874](https://github.com/seata/seata/pull/4874)] fix startup failure of Server1.5.2 by using OpenJDK 11
- [[#5018](https://github.com/seata/seata/pull/5018)] fix loader path in startup scripts
- [[#5004](https://github.com/seata/seata/pull/5004)] fix duplicate image row for update join
- [[#5032](https://github.com/seata/seata/pull/5032)] fix mysql InsertOnDuplicateUpdate sql query error caused by placeholder index calculation error
- [[#5033](https://github.com/seata/seata/pull/5033)] fix null exception when sql columns is empty for insert on duplicate
- [[#5033](https://github.com/seata/seata/pull/5023)] fix mysql InsertOnDuplicateUpdate insert value type recognize error
- [[#5038](https://github.com/seata/seata/pull/5038)] remove @EnableConfigurationProperties({SagaAsyncThreadPoolProperties.class})
- [[#5050](https://github.com/seata/seata/pull/5050)] fix global session is not change to Committed in saga mode
- [[#5052](https://github.com/seata/seata/pull/5052)] fix update join condition placeholder param error
- [[#5031](https://github.com/seata/seata/pull/5031)] fix mysql InsertOnDuplicateUpdate should not use null index value as image sql query condition


### optimize:
Expand Down
2 changes: 2 additions & 0 deletions changes/zh-cn/develop.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@
- [[#4874](https://github.com/seata/seata/pull/4874)] 修复OpenJDK 11 Server1.5.2 启动失败
- [[#5018](https://github.com/seata/seata/pull/5018)] 修复启动脚本中 loader path 使用相对路径导致 server 启动失败问题
- [[#5004](https://github.com/seata/seata/pull/5004)] 修复mysql update join行数据重复的问题
- [[#5032](https://github.com/seata/seata/pull/5032)] 修复mysql InsertOnDuplicateUpdate中条件参数填充位置计算错误导致的镜像查询SQL语句异常问题
- [[#5033](https://github.com/seata/seata/pull/5033)] 修复InsertOnDuplicateUpdate的SQL语句中无插入列字段导致的空指针问题
- [[#5033](https://github.com/seata/seata/pull/5023)] 修复InsertOnDuplicateUpdate中插入值解析为String类型导致的类型识别错误
- [[#5038](https://github.com/seata/seata/pull/5038)] 修复SagaAsyncThreadPoolProperties冲突问题
- [[#5050](https://github.com/seata/seata/pull/5050)] 修复Saga模式下全局状态未正确更改成Committed
- [[#5052](https://github.com/seata/seata/pull/5052)] 修复update join条件中占位符参数问题
- [[#5031](https://github.com/seata/seata/pull/5031)] 修复InsertOnDuplicateUpdate中不应该使用null值索引作为查询条件

### optimize:
- [[#4774](https://github.com/seata/seata/pull/4774)] 优化 seataio/seata-server 镜像中的 mysql8 依赖
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import io.seata.rm.datasource.sql.struct.Row;
import io.seata.rm.datasource.sql.struct.TableMeta;
import io.seata.rm.datasource.sql.struct.TableRecords;
import io.seata.rm.datasource.sql.struct.IndexMeta;
import io.seata.rm.datasource.undo.SQLUndoLog;
import io.seata.sqlparser.SQLInsertRecognizer;
import io.seata.sqlparser.SQLRecognizer;
Expand Down Expand Up @@ -237,7 +238,9 @@ protected TableRecords afterImage(TableRecords beforeImage) throws SQLException
primaryValues.add(v);
}
});
afterImageSql.append(" OR (").append(Joiner.on(" and ").join(wherePrimaryList)).append(") ");
if (wherePrimaryList.size() > 0) {
afterImageSql.append(" OR (").append(Joiner.on(" and ").join(wherePrimaryList)).append(") ");
}
}

return buildTableRecords2(tableMeta, afterImageSql.toString(), paramAppenderList, primaryValues);
Expand Down Expand Up @@ -268,17 +271,18 @@ public TableRecords buildTableRecords2(TableMeta tableMeta, String selectSQL, Ar
ResultSet rs = null;
try (PreparedStatement ps = statementProxy.getConnection()
.prepareStatement(primaryKeys.isEmpty() ? selectSQL + " FOR UPDATE" : selectSQL)) {
int paramAppenderCount = 0;
int ts = CollectionUtils.isEmpty(paramAppenderList) ? 0 : paramAppenderList.size();
int ds = ts == 0 ? 0 : paramAppenderList.get(0).size();
for (int i = 0; i < ts; i++) {
List<Object> paramAppender = paramAppenderList.get(i);
for (int j = 0; j < ds; j++) {
for (int j = 0; j < paramAppender.size(); j++) {
Object param = paramAppender.get(j);
ps.setObject(i * ds + j + 1, (param instanceof Null) ? null : param);
ps.setObject(paramAppenderCount + 1, (param instanceof Null) ? null : param);
paramAppenderCount++;
}
}
for (int i = 0; i < primaryKeys.size(); i++) {
ps.setObject(ts * ds + i + 1, primaryKeys.get(i));
ps.setObject(paramAppenderCount + i + 1, primaryKeys.get(i));
}

rs = ps.executeQuery();
Expand Down Expand Up @@ -308,7 +312,7 @@ public String buildImageSQL(TableMeta tableMeta) {
int finalI = i;
List<Object> paramAppenderTempList = new ArrayList<>();
tableMeta.getAllIndexes().forEach((k, v) -> {
if (!v.isNonUnique()) {
if (!v.isNonUnique() && isIndexValueNotNull(v,imageParameterMap,finalI)) {
boolean columnIsNull = true;
List<String> uniqueList = new ArrayList<>();
for (ColumnMeta m : v.getValues()) {
Expand All @@ -322,15 +326,6 @@ public String buildImageSQL(TableMeta tableMeta) {
columnIsNull = false;
continue;
}
if ((imageParameters == null && m.getColumnDef() == null) || imageParameters.get(finalI) == null || imageParameters.get(finalI) instanceof Null) {
if (!"PRIMARY".equalsIgnoreCase(k)) {
columnIsNull = false;
uniqueList.add(columnName + " is ? ");
paramAppenderTempList.add("NULL");
continue;
}
break;
}
if ("PRIMARY".equalsIgnoreCase(k)) {
primaryKeysInBeforeImageSql.add(columnName);
}
Expand Down Expand Up @@ -404,4 +399,17 @@ public Map<String, ArrayList<Object>> buildImageParameters(SQLInsertRecognizer r
return imageParameterMap;
}

private boolean isIndexValueNotNull(IndexMeta indexMeta, Map<String, ArrayList<Object>> imageParameterMap,int rowIndex) {
for (ColumnMeta columnMeta : indexMeta.getValues()) {
String columnName = columnMeta.getColumnName();
List<Object> imageParameters = imageParameterMap.get(columnName);
if (imageParameters == null && columnMeta.getColumnDef() == null) {
return false;
} else if (imageParameters != null && (imageParameters.get(rowIndex) == null || imageParameters.get(rowIndex) instanceof Null)) {
return false;
}
}
return true;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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.
*/
package io.seata.rm.datasource.exec.oracle;

/**
* @author doubleDimple lovele.cn@gmail.com
*/
public class OracleJdbcType {

public static final int TIMESTAMP_WITH_TIME_ZONE = -101;

public static final int TIMESTAMP_WITH_LOCAL_TIME_ZONE = -102;
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
import javax.sql.rowset.serial.SerialRef;
import io.seata.common.exception.ShouldNeverHappenException;
import io.seata.rm.datasource.sql.serial.SerialArray;
import static io.seata.rm.datasource.exec.oracle.OracleJdbcType.TIMESTAMP_WITH_LOCAL_TIME_ZONE;
import static io.seata.rm.datasource.exec.oracle.OracleJdbcType.TIMESTAMP_WITH_TIME_ZONE;
import static io.seata.rm.datasource.util.OffsetTimeUtils.convertOffSetTime;
import static io.seata.rm.datasource.util.OffsetTimeUtils.timeToOffsetDateTime;

/**
* The type Table records.
Expand Down Expand Up @@ -237,6 +241,8 @@ public static TableRecords buildRecords(TableMeta tmeta, ResultSet resultSet) th
if (object != null) {
field.setValue(new SerialJavaObject(object));
}
} else if (dataType == TIMESTAMP_WITH_TIME_ZONE || dataType == TIMESTAMP_WITH_LOCAL_TIME_ZONE) {
field.setValue(convertOffSetTime(timeToOffsetDateTime(resultSet.getBytes(i))));
} else {
// JDBCType.DISTINCT, JDBCType.STRUCT etc...
field.setValue(holdSerialDataType(resultSet.getObject(i)));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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.
*/
package io.seata.rm.datasource.util;

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

import static java.lang.Short.toUnsignedInt;
import static java.time.ZoneOffset.UTC;

/**
* Currently, common time zones are supported
*
* @see java.time.ZoneId
*
*
* @author doubleDimple
*/
public class OffsetTimeUtils {

public static final String PATTERN_FORMAT_TIME = "yyyy-MM-dd HH:mm:ss.SSS";

private static final byte REGIONIDBIT = (byte)0b1000_0000;

private static final Map<Integer, String> ZONE_ID_MAP = new HashMap<>(36);

public static String getRegion(int code) {
return ZONE_ID_MAP.get(code);
}

public static String convertOffSetTime(OffsetDateTime offsetDateTime) {
if (null != offsetDateTime) {
return offsetDateTime.format(DateTimeFormatter.ofPattern(PATTERN_FORMAT_TIME));
}
return null;
}

public static OffsetDateTime timeToOffsetDateTime(byte[] bytes) {
if (null == bytes || bytes.length == 0) {
return null;
}

OffsetDateTime utc = extractUtc(bytes);
if (bytes.length >= 8) {
if (isFixedOffset(bytes)) {
ZoneOffset offset = extractOffset(bytes);
return utc.withOffsetSameInstant(offset);
} else {
ZoneId zoneId = extractZoneId(bytes);
return utc.atZoneSameInstant(zoneId).toOffsetDateTime();
}
}
return utc.atZoneSameInstant(ZoneId.systemDefault()).toOffsetDateTime();
}

private static boolean isFixedOffset(byte[] bytes) {
return (bytes[11] & REGIONIDBIT) == 0;
}

private static OffsetDateTime extractUtc(byte[] bytes) {
return OffsetDateTime.of(extractLocalDateTime(bytes), UTC);
}

private static ZoneId extractZoneId(byte[] bytes) {
// high order bits
int regionCode = (bytes[11] & 0b1111111) << 6;
// low order bits
regionCode += (bytes[12] & 0b11111100) >> 2;
String regionName = getRegion(regionCode);
return ZoneId.of(regionName);
}

private static ZoneOffset extractOffset(byte[] bytes) {
int hours = bytes[11] - 20;
int minutes = bytes[12] - 60;
if ((hours == 0) && (minutes == 0)) {
return ZoneOffset.UTC;
}
return ZoneOffset.ofHoursMinutes(hours, minutes);
}

private static LocalDateTime extractLocalDateTime(byte[] bytes) {
int year = ((toUnsignedInt(bytes[0]) - 100) * 100) + (toUnsignedInt(bytes[1]) - 100);
int month = bytes[2];
int dayOfMonth = bytes[3];
int hour = bytes[4] - 1;
int minute = bytes[5] - 1;
int second = bytes[6] - 1;
int nanoOfSecond = 0;
if (bytes.length >= 8) {
nanoOfSecond = (toUnsignedInt(bytes[7]) << 24) | (toUnsignedInt(bytes[8]) << 16)
| (toUnsignedInt(bytes[9]) << 8) | toUnsignedInt(bytes[10]);
}
return LocalDateTime.of(year, month, dayOfMonth, hour, minute, second, nanoOfSecond);
}

static {
ZONE_ID_MAP.put(250, "Asia/Shanghai");
ZONE_ID_MAP.put(345, "Australia/Darwin");
ZONE_ID_MAP.put(352, "Australia/Sydney");
ZONE_ID_MAP.put(687, "America/Argentina/Buenos_Aires");
ZONE_ID_MAP.put(106, "America/Anchorage");
ZONE_ID_MAP.put(188, "America/Sao_Paulo");
ZONE_ID_MAP.put(756, "Asia/Dhaka");
ZONE_ID_MAP.put(80, "Africa/Harare");
ZONE_ID_MAP.put(118, "America/St_Johns");
ZONE_ID_MAP.put(101, "America/Chicago");
ZONE_ID_MAP.put(47, "Africa/Addis_Ababa");
ZONE_ID_MAP.put(382, "Europe/Paris");
ZONE_ID_MAP.put(1647, "America/Indiana/Indianapolis");
ZONE_ID_MAP.put(772, "Asia/Kolkata");
ZONE_ID_MAP.put(267, "Asia/Tokyo");
ZONE_ID_MAP.put(479, "Pacific/Apia");
ZONE_ID_MAP.put(241, "Asia/Yerevan");
ZONE_ID_MAP.put(471, "Pacific/Auckland");
ZONE_ID_MAP.put(284, "Asia/Karachi");
ZONE_ID_MAP.put(109, "America/Phoenix");
ZONE_ID_MAP.put(167, "America/Puerto_Rico");
ZONE_ID_MAP.put(103, "America/Los_Angeles");
ZONE_ID_MAP.put(481, "Pacific/Guadalcanal");
ZONE_ID_MAP.put(813, "Asia/Ho_Chi_Minh");
ZONE_ID_MAP.put(1474, "HST");
ZONE_ID_MAP.put(1636, "EST");
ZONE_ID_MAP.put(2662, "MST");
}
}

0 comments on commit 27ad395

Please sign in to comment.