-
Notifications
You must be signed in to change notification settings - Fork 8.9k
bugfix: fix wrong PK parameter index in batch INSERT with function expressions #8028
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
base: 2.x
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -151,6 +151,16 @@ protected Map<String, List<Object>> parsePkValuesFromStatement() { | |
| Map<Integer, ArrayList<Object>> parameters = preparedStatementProxy.getParameters(); | ||
| final int rowSize = insertRows.size(); | ||
| int totalPlaceholderNum = -1; | ||
| // Calculate the number of hidden JDBC parameters per row caused by function | ||
| // expressions (e.g. ST_GeomFromText(CONCAT('POINT(', ?, ' ', ?, ')'))) that | ||
| // contain parameter placeholders not visible in the parsed row structure. | ||
| int nonEmptyRowCount = 0; | ||
| for (List<Object> r : insertRows) { | ||
| if (!r.isEmpty()) { | ||
| nonEmptyRowCount++; | ||
| } | ||
| } | ||
| int hiddenParamsPerRow = 0; | ||
| for (List<Object> row : insertRows) { | ||
| // oracle insert sql statement specify RETURN_GENERATED_KEYS will append :rowid on sql end | ||
| // insert parameter count will than the actual +1 | ||
|
|
@@ -164,6 +174,13 @@ protected Map<String, List<Object>> parsePkValuesFromStatement() { | |
| currentRowPlaceholderNum += 1; | ||
| } | ||
| } | ||
| if (hiddenParamsPerRow == 0 && nonEmptyRowCount > 0) { | ||
| int visiblePlaceholdersPerRow = currentRowPlaceholderNum + 1; | ||
| int actualParamsPerRow = parameters.size() / nonEmptyRowCount; | ||
| if (actualParamsPerRow > visiblePlaceholdersPerRow) { | ||
| hiddenParamsPerRow = actualParamsPerRow - visiblePlaceholdersPerRow; | ||
| } | ||
| } | ||
|
Comment on lines
+177
to
+183
|
||
| String pkKey; | ||
| int pkIndex; | ||
| List<Object> pkValues; | ||
|
|
@@ -177,16 +194,39 @@ protected Map<String, List<Object>> parsePkValuesFromStatement() { | |
| Object pkValue = row.get(pkIndex); | ||
| if (PLACEHOLDER.equals(pkValue)) { | ||
| int currentRowNotPlaceholderNumBeforePkIndex = 0; | ||
| for (int n = 0, len = row.size(); n < len; n++) { | ||
| Object r = row.get(n); | ||
| if (n < pkIndex && !PLACEHOLDER.equals(r)) { | ||
| currentRowNotPlaceholderNumBeforePkIndex++; | ||
| int hiddenParamsBeforePk = 0; | ||
| if (hiddenParamsPerRow > 0) { | ||
| int sqlMethodExprCountTotal = 0; | ||
| int sqlMethodExprCountBeforePk = 0; | ||
| for (int n = 0, len = row.size(); n < len; n++) { | ||
| Object r = row.get(n); | ||
| if (r instanceof SqlMethodExpr) { | ||
| sqlMethodExprCountTotal++; | ||
| if (n < pkIndex) { | ||
| sqlMethodExprCountBeforePk++; | ||
| } | ||
| } | ||
| if (n < pkIndex && !PLACEHOLDER.equals(r)) { | ||
| currentRowNotPlaceholderNumBeforePkIndex++; | ||
| } | ||
| } | ||
| if (sqlMethodExprCountTotal > 0) { | ||
| hiddenParamsBeforePk = hiddenParamsPerRow | ||
| * sqlMethodExprCountBeforePk / sqlMethodExprCountTotal; | ||
| } | ||
| } else { | ||
| for (int n = 0, len = row.size(); n < len; n++) { | ||
| Object r = row.get(n); | ||
| if (n < pkIndex && !PLACEHOLDER.equals(r)) { | ||
| currentRowNotPlaceholderNumBeforePkIndex++; | ||
| } | ||
| } | ||
| } | ||
| int idx = totalPlaceholderNum | ||
| - currentRowPlaceholderNum | ||
| + pkIndex | ||
| - currentRowNotPlaceholderNumBeforePkIndex; | ||
| - currentRowNotPlaceholderNumBeforePkIndex | ||
| + hiddenParamsBeforePk; | ||
| ArrayList<Object> parameter = parameters.get(idx + 1); | ||
| pkValues.addAll(parameter); | ||
| } else { | ||
|
|
@@ -196,6 +236,9 @@ protected Map<String, List<Object>> parsePkValuesFromStatement() { | |
| pkValuesMap.put(ColumnUtils.delEscape(pkKey, getDbType()), pkValues); | ||
| } | ||
| } | ||
| // Adjust totalPlaceholderNum to account for hidden parameters inside | ||
| // function expressions, so the next row's parameter offset is correct. | ||
| totalPlaceholderNum += hiddenParamsPerRow; | ||
|
Comment on lines
+239
to
+241
|
||
| } | ||
| } | ||
| } else { | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -881,4 +881,209 @@ private void mockInsertRows() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rows.add(Arrays.asList("?", "?", "?", "?")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(rows); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Test that batch INSERT with function expressions containing hidden JDBC parameters | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * correctly extracts PK values for all rows. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Simulates: INSERT INTO t(id, name, location) VALUES | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * (?, ?, ST_GeomFromText(CONCAT('POINT(', ?, ' ', ?, ')'))), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * (?, ?, ST_GeomFromText(CONCAT('POINT(', ?, ' ', ?, ')'))), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * (?, ?, ST_GeomFromText(CONCAT('POINT(', ?, ' ', ?, ')'))) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Each row has 2 visible placeholders + 2 hidden placeholders inside the function = 4 actual JDBC params per row. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * See: https://github.com/apache/incubator-seata/issues/6941 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Test | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public void testGetPkValuesByColumn_BatchInsertWithFunctionExpression() throws SQLException { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+897
to
+898
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Setup: 3 columns (id, name, location), PK is id at index 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| List<String> columns = new ArrayList<>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| columns.add(ID_COLUMN); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| columns.add(USER_NAME_COLUMN); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| columns.add("location"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| when(sqlInsertRecognizer.getInsertColumns()).thenReturn(columns); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+899
to
+904
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Row structure: ["?", "?", SqlMethodExpr] — function hides 2 extra params | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| List<List<Object>> rows = new ArrayList<>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rows.add(Arrays.asList("?", "?", SqlMethodExpr.get())); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rows.add(Arrays.asList("?", "?", SqlMethodExpr.get())); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rows.add(Arrays.asList("?", "?", SqlMethodExpr.get())); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(rows); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+906
to
+911
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // JDBC parameters: 4 per row (id, name, x, y), 12 total | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Map<Integer, ArrayList<Object>> parameters = new HashMap<>(12); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Row 1: id=1, name="name1", x=10.0, y=20.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parameters.put(1, new ArrayList<>(Arrays.asList(1))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parameters.put(2, new ArrayList<>(Arrays.asList("name1"))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parameters.put(3, new ArrayList<>(Arrays.asList(10.0))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parameters.put(4, new ArrayList<>(Arrays.asList(20.0))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Row 2: id=2, name="name2", x=30.0, y=40.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parameters.put(5, new ArrayList<>(Arrays.asList(2))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parameters.put(6, new ArrayList<>(Arrays.asList("name2"))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parameters.put(7, new ArrayList<>(Arrays.asList(30.0))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parameters.put(8, new ArrayList<>(Arrays.asList(40.0))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Row 3: id=3, name="name3", x=50.0, y=60.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parameters.put(9, new ArrayList<>(Arrays.asList(3))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parameters.put(10, new ArrayList<>(Arrays.asList("name3"))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parameters.put(11, new ArrayList<>(Arrays.asList(50.0))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parameters.put(12, new ArrayList<>(Arrays.asList(60.0))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PreparedStatementProxy psp = (PreparedStatementProxy) this.statementProxy; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| when(psp.getParameters()).thenReturn(parameters); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| doReturn(tableMeta).when(insertExecutor).getTableMeta(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[] {ID_COLUMN})); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| doReturn(pkIndexMap).when(insertExecutor).getPkIndex(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Map<String, List<Object>> pkValuesList = insertExecutor.getPkValuesByColumn(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| List<Object> idValues = pkValuesList.get(ID_COLUMN); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Assertions.assertNotNull(idValues); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Assertions.assertEquals(3, idValues.size()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Assertions.assertEquals(1, idValues.get(0)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Assertions.assertEquals(2, idValues.get(1)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Assertions.assertEquals(3, idValues.get(2)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+898
to
+944
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public void testGetPkValuesByColumn_BatchInsertWithFunctionExpression() throws SQLException { | |
| // Setup: 3 columns (id, name, location), PK is id at index 0 | |
| List<String> columns = new ArrayList<>(); | |
| columns.add(ID_COLUMN); | |
| columns.add(USER_NAME_COLUMN); | |
| columns.add("location"); | |
| when(sqlInsertRecognizer.getInsertColumns()).thenReturn(columns); | |
| // Row structure: ["?", "?", SqlMethodExpr] — function hides 2 extra params | |
| List<List<Object>> rows = new ArrayList<>(); | |
| rows.add(Arrays.asList("?", "?", SqlMethodExpr.get())); | |
| rows.add(Arrays.asList("?", "?", SqlMethodExpr.get())); | |
| rows.add(Arrays.asList("?", "?", SqlMethodExpr.get())); | |
| when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(rows); | |
| // JDBC parameters: 4 per row (id, name, x, y), 12 total | |
| Map<Integer, ArrayList<Object>> parameters = new HashMap<>(12); | |
| // Row 1: id=1, name="name1", x=10.0, y=20.0 | |
| parameters.put(1, new ArrayList<>(Arrays.asList(1))); | |
| parameters.put(2, new ArrayList<>(Arrays.asList("name1"))); | |
| parameters.put(3, new ArrayList<>(Arrays.asList(10.0))); | |
| parameters.put(4, new ArrayList<>(Arrays.asList(20.0))); | |
| // Row 2: id=2, name="name2", x=30.0, y=40.0 | |
| parameters.put(5, new ArrayList<>(Arrays.asList(2))); | |
| parameters.put(6, new ArrayList<>(Arrays.asList("name2"))); | |
| parameters.put(7, new ArrayList<>(Arrays.asList(30.0))); | |
| parameters.put(8, new ArrayList<>(Arrays.asList(40.0))); | |
| // Row 3: id=3, name="name3", x=50.0, y=60.0 | |
| parameters.put(9, new ArrayList<>(Arrays.asList(3))); | |
| parameters.put(10, new ArrayList<>(Arrays.asList("name3"))); | |
| parameters.put(11, new ArrayList<>(Arrays.asList(50.0))); | |
| parameters.put(12, new ArrayList<>(Arrays.asList(60.0))); | |
| PreparedStatementProxy psp = (PreparedStatementProxy) this.statementProxy; | |
| when(psp.getParameters()).thenReturn(parameters); | |
| doReturn(tableMeta).when(insertExecutor).getTableMeta(); | |
| when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[] {ID_COLUMN})); | |
| doReturn(pkIndexMap).when(insertExecutor).getPkIndex(); | |
| Map<String, List<Object>> pkValuesList = insertExecutor.getPkValuesByColumn(); | |
| List<Object> idValues = pkValuesList.get(ID_COLUMN); | |
| Assertions.assertNotNull(idValues); | |
| Assertions.assertEquals(3, idValues.size()); | |
| Assertions.assertEquals(1, idValues.get(0)); | |
| Assertions.assertEquals(2, idValues.get(1)); | |
| Assertions.assertEquals(3, idValues.get(2)); | |
| private void stubInsertColumns(String... columns) { | |
| when(sqlInsertRecognizer.getInsertColumns()).thenReturn(Arrays.asList(columns)); | |
| } | |
| private void stubInsertRows(List<List<Object>> rows) { | |
| when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(rows); | |
| } | |
| private void stubParameters(Object... parameterValues) { | |
| Map<Integer, ArrayList<Object>> parameters = new HashMap<>(parameterValues.length); | |
| for (int i = 0; i < parameterValues.length; i++) { | |
| parameters.put(i + 1, new ArrayList<>(Arrays.asList(parameterValues[i]))); | |
| } | |
| PreparedStatementProxy psp = (PreparedStatementProxy) this.statementProxy; | |
| when(psp.getParameters()).thenReturn(parameters); | |
| } | |
| private void stubPkMetadata() throws SQLException { | |
| doReturn(tableMeta).when(insertExecutor).getTableMeta(); | |
| when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[] {ID_COLUMN})); | |
| doReturn(pkIndexMap).when(insertExecutor).getPkIndex(); | |
| } | |
| private void assertPkValues(Map<String, List<Object>> pkValuesList, String pkColumn, Object... expectedValues) { | |
| List<Object> actualValues = pkValuesList.get(pkColumn); | |
| Assertions.assertNotNull(actualValues); | |
| Assertions.assertEquals(expectedValues.length, actualValues.size()); | |
| for (int i = 0; i < expectedValues.length; i++) { | |
| Assertions.assertEquals(expectedValues[i], actualValues.get(i)); | |
| } | |
| } | |
| public void testGetPkValuesByColumn_BatchInsertWithFunctionExpression() throws SQLException { | |
| stubInsertColumns(ID_COLUMN, USER_NAME_COLUMN, "location"); | |
| List<List<Object>> rows = new ArrayList<>(); | |
| rows.add(Arrays.asList("?", "?", SqlMethodExpr.get())); | |
| rows.add(Arrays.asList("?", "?", SqlMethodExpr.get())); | |
| rows.add(Arrays.asList("?", "?", SqlMethodExpr.get())); | |
| stubInsertRows(rows); | |
| stubParameters( | |
| 1, "name1", 10.0, 20.0, | |
| 2, "name2", 30.0, 40.0, | |
| 3, "name3", 50.0, 60.0 | |
| ); | |
| stubPkMetadata(); | |
| Map<String, List<Object>> pkValuesList = insertExecutor.getPkValuesByColumn(); | |
| assertPkValues(pkValuesList, ID_COLUMN, 1, 2, 3); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The inferred
actualParamsPerRow = parameters.size() / nonEmptyRowCountcan be wrong whenparameters.size()includes non-row parameters (the comment above already calls out OracleRETURN_GENERATED_KEYSadding an extra binding). This is especially problematic whennonEmptyRowCount == 1, where the extra binding is not eliminated by integer division and can incorrectly sethiddenParamsPerRow, shifting PK indices. A safer approach is to account for a remainder explicitly (e.g., wheninsertRowscontains an appended empty row andparameters.size() % nonEmptyRowCount == 1, compute(parameters.size() - 1) / nonEmptyRowCount), and/or only derive hidden params when the row-parameter total cleanly matches the row count.