Skip to content

Commit

Permalink
0006363: Auto resolve delete of blocking rows when binary type in
Browse files Browse the repository at this point in the history
primary key
  • Loading branch information
erilong committed Apr 29, 2024
1 parent d1e6d3d commit 41c4fef
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 40 deletions.
17 changes: 17 additions & 0 deletions symmetric-db/src/main/java/org/jumpmind/db/sql/Row.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.Set;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.io.IOUtils;
Expand All @@ -56,6 +57,12 @@ public Row(String columnName, Object value) {
put(columnName, value);
}

public Row(String[] names, Object[] values) {
for (int i = 0; i < names.length && i < values.length; i++) {
put(names[i], values[i]);
}
}

public byte[] bytesValue() {
Object obj = this.values().iterator().next();
return toBytes(obj);
Expand Down Expand Up @@ -324,6 +331,16 @@ public Object[] toArray(String[] keys) {
return values;
}

public Object[] toArray() {
Set<String> keys = keySet();
Object[] values = new Object[keys.size()];
int i = 0;
for (String key : keys) {
values[i++] = get(key);
}
return values;
}

public String[] toStringArray(String[] keys) {
String[] values = new String[keys.length];
for (int i = 0; i < keys.length; i++) {
Expand Down
9 changes: 0 additions & 9 deletions symmetric-db/src/main/java/org/jumpmind/db/util/TableRow.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
*/
package org.jumpmind.db.util;

import java.util.Map;

import org.jumpmind.db.model.ForeignKey;
import org.jumpmind.db.model.Reference;
import org.jumpmind.db.model.Table;
Expand All @@ -43,13 +41,6 @@ public TableRow(Table table, Row row, String whereSql, String referenceColumnNam
this.fkName = fkName;
}

public TableRow(Table table, Map<String, String> rowValues, String whereSql, String referenceColumnName,
String fkName) {
this(table, (Row) null, whereSql, referenceColumnName, fkName);
row = new Row(rowValues.size());
row.putAll(rowValues);
}

protected String getFkColumnValues() {
if (fkColumnValues == null) {
StringBuilder builder = new StringBuilder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -575,8 +575,7 @@ protected int deleteRow(IDatabasePlatform platform, ISqlTemplate sqlTemplate, De
databaseWriter.getWriterSettings().getTextColumnExpression());
// Query the row that we need to delete because it is blocking us
Row uniqueRow = queryForRow(platform, databaseWriter, selectStmt.getSql(), objectValues);
CsvData uniqueData = new CsvData(DataEventType.INSERT, uniqueRow.toStringArray(targetTable.getColumnNames()));
if (deleteForeignKeyChildren(platform, sqlTemplate, databaseWriter, targetTable, uniqueData)) {
if (deleteForeignKeyChildren(platform, sqlTemplate, databaseWriter, targetTable, null, uniqueRow)) {
count = prepareAndExecute(platform, databaseWriter, sql, objectValues);
}
} else {
Expand All @@ -602,7 +601,7 @@ protected boolean checkForForeignKeyChildExistsViolation(AbstractDatabaseWriter
}
log.info("Child exists foreign key violation on table {} during {} with batch {}. Attempting to correct.",
targetTable.getName(), data.getDataEventType().toString(), writer.getContext().getBatch().getNodeBatchId());
if (deleteForeignKeyChildren(platform, sqlTemplate, databaseWriter, writer.getTargetTable(), data)) {
if (deleteForeignKeyChildren(platform, sqlTemplate, databaseWriter, writer.getTargetTable(), data, null)) {
return true;
} else {
throw new RuntimeException("Failed to delete foreign table rows to fix foreign key violation for table '"
Expand All @@ -613,33 +612,24 @@ protected boolean checkForForeignKeyChildExistsViolation(AbstractDatabaseWriter
}

protected boolean deleteForeignKeyChildren(IDatabasePlatform platform, ISqlTemplate sqlTemplate, DefaultDatabaseWriter databaseWriter, Table targetTable,
CsvData data) {
Map<String, String> values = null;
CsvData data, Row row) {
List<TableRow> tableRows = new ArrayList<TableRow>();
if (data.getDataEventType() == DataEventType.INSERT) {
values = data.toColumnNameValuePairs(databaseWriter.getSourceTable().getColumnNames(), CsvData.ROW_DATA);
BinaryEncoding encoding = databaseWriter.getBatch().getBinaryEncoding();
Table sourceTable = databaseWriter.getSourceTable();
if (row != null) {
tableRows.add(new TableRow(targetTable, row, null, null, null));
} else if (data.getDataEventType() == DataEventType.INSERT) {
Object[] objectValues = platform.getObjectValues(encoding, data.getParsedData(CsvData.ROW_DATA), sourceTable.getColumns());
tableRows.add(new TableRow(targetTable, new Row(sourceTable.getColumnNames(), objectValues), null, null, null));
} else {
values = data.toColumnNameValuePairs(databaseWriter.getSourceTable().getColumnNames(), CsvData.OLD_DATA);
if (values == null || values.size() == 0) {
values = data.toColumnNameValuePairs(databaseWriter.getSourceTable().getPrimaryKeyColumnNames(), CsvData.PK_DATA);
Row whereRow = new Row(values.size());
boolean[] nullValues = new boolean[values.size()];
int index = 0;
for (Entry<String, String> entry : values.entrySet()) {
nullValues[index++] = entry.getValue() == null;
whereRow.put(entry.getKey(), entry.getValue());
}
DmlStatement whereSt = platform.createDmlStatement(DmlType.WHERE, targetTable.getCatalog(),
targetTable.getSchema(), targetTable.getName(), targetTable.getPrimaryKeyColumns(),
targetTable.getColumns(), nullValues, null);
String whereSql = whereSt.buildDynamicSql(BinaryEncoding.HEX, whereRow, false, true,
targetTable.getPrimaryKeyColumns()).substring(6);
String delimiter = platform.getDatabaseInfo().getSqlCommandDelimiter();
if (delimiter != null && delimiter.length() > 0) {
whereSql = whereSql.substring(0, whereSql.length() - delimiter.length());
}
String[] oldData = data.getParsedData(CsvData.OLD_DATA);
String[] pkData = data.getParsedData(CsvData.PK_DATA);
if (oldData != null && oldData.length > 0) {
Object[] objectValues = platform.getObjectValues(encoding, oldData, sourceTable.getColumns());
tableRows.add(new TableRow(targetTable, new Row(sourceTable.getColumnNames(), objectValues), null, null, null));
} else if (pkData != null && pkData.length > 0) {
Object[] keys = platform.getObjectValues(encoding, pkData, sourceTable.getColumns());
DmlStatement selectSt = platform.createDmlStatement(DmlType.SELECT, targetTable, null);
Object[] keys = whereRow.toArray(targetTable.getPrimaryKeyColumnNames());
Row targetRow = doInTransaction(platform, databaseWriter, new ITransactionCallback<Row>() {
public Row execute(ISqlTransaction transaction) {
return transaction.queryForRow(selectSt.getSql(), keys);
Expand All @@ -651,7 +641,8 @@ public Row execute(ISqlTransaction transaction) {
}
}
if (tableRows.isEmpty()) {
tableRows.add(new TableRow(targetTable, values, null, null, null));
Object[] objectValues = platform.getObjectValues(encoding, data.getParsedData(CsvData.ROW_DATA), sourceTable.getColumns());
tableRows.add(new TableRow(targetTable, new Row(sourceTable.getColumnNames(), objectValues), null, null, null));
}
List<TableRow> foreignTableRows = doInTransaction(platform, databaseWriter, new ITransactionCallback<List<TableRow>>() {
public List<TableRow> execute(ISqlTransaction transaction) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1603,9 +1603,7 @@ public List<TableRow> getExportedForeignTableRows(ISqlTransaction transaction, L
DmlStatement selectSt = platform.createDmlStatement(DmlType.SELECT, foreignTable.getCatalog(),
foreignTable.getSchema(), foreignTable.getName(), keyColumns,
foreignTable.getColumns(), nullValues, null);
Object[] selectValues = platform.getObjectValues(encoding, selectRow.toStringArray(selectRow.keySet().toArray(new String[0])),
keyColumns);
List<Row> rows = transaction.query(selectSt.getSql(), new RowMapper(), selectValues, selectSt.getTypes());
List<Row> rows = transaction.query(selectSt.getSql(), new RowMapper(), selectRow.toArray(), selectSt.getTypes());
if (rows != null) {
for (Row row : rows) {
DmlStatement whereSt = null;
Expand Down

0 comments on commit 41c4fef

Please sign in to comment.