Skip to content

Commit 8162706

Browse files
divangmobilebilly
andauthored
Add order Hints for Bulk Copy operations (#2701)
* Add order Hints for Bulk Copy operations (#1481) * Add unit test cases to the column order hints enhancement --------- Co-authored-by: mobilebilly <[email protected]>
1 parent 3ab4611 commit 8162706

File tree

6 files changed

+419
-3
lines changed

6 files changed

+419
-3
lines changed

src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import java.util.Collections;
3939
import java.util.GregorianCalendar;
4040
import java.util.HashMap;
41+
import java.util.HashSet;
4142
import java.util.Iterator;
4243
import java.util.List;
4344
import java.util.Locale;
@@ -111,6 +112,22 @@ private class ColumnMapping implements Serializable {
111112
}
112113
}
113114

115+
private class ColumnOrderHint implements Serializable {
116+
/**
117+
* Always update serialVersionUID when prompted.
118+
*/
119+
private static final long serialVersionUID = 6132627333120344137L;
120+
121+
String columnName = null;
122+
123+
SQLServerSortOrder sortOrder;
124+
125+
ColumnOrderHint(String columnName, SQLServerSortOrder sortOrder) {
126+
this.columnName = columnName;
127+
this.sortOrder = sortOrder;
128+
}
129+
}
130+
114131
/**
115132
* Class name for logging.
116133
*/
@@ -136,6 +153,11 @@ private class ColumnMapping implements Serializable {
136153
*/
137154
private List<ColumnMapping> columnMappings;
138155

156+
/**
157+
* Column order hints describe the sort order of columns in the clustered index of the destination
158+
*/
159+
private List<ColumnOrderHint> columnOrderHints;
160+
139161
/**
140162
* Flag if SQLServerBulkCopy owns the connection and should close it when Close is called
141163
*/
@@ -457,6 +479,43 @@ public void clearColumnMappings() {
457479
loggerExternal.exiting(loggerClassName, "clearColumnMappings");
458480
}
459481

482+
/**
483+
* Adds a new column order hint, specify the column name and sort order
484+
*
485+
* @param columnName
486+
* Column name.
487+
* @param sortOrder
488+
* Column sort order.
489+
* @throws SQLServerException
490+
* If the column order hint is invalid
491+
*/
492+
public void addColumnOrderHint(String columnName, SQLServerSortOrder sortOrder) throws SQLServerException {
493+
if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) {
494+
loggerExternal.entering(loggerClassName, "addColumnOrderHint",
495+
new Object[] {columnName, sortOrder});
496+
}
497+
498+
if (null == columnName || columnName.isEmpty()) {
499+
throwInvalidArgument("columnName");
500+
} else if (null == sortOrder || SQLServerSortOrder.UNSPECIFIED == sortOrder) {
501+
throwInvalidArgument("sortOrder");
502+
}
503+
columnOrderHints.add(new ColumnOrderHint(columnName, sortOrder));
504+
505+
loggerExternal.exiting(loggerClassName, "addColumnOrderHint");
506+
}
507+
508+
/**
509+
* Clears the contents of the column order hints
510+
*/
511+
public void clearColumnOrderHints() {
512+
loggerExternal.entering(loggerClassName, "clearColumnOrderHints");
513+
514+
columnOrderHints.clear();
515+
516+
loggerExternal.exiting(loggerClassName, "clearColumnOrderHints");
517+
}
518+
460519
/**
461520
* Closes the SQLServerBulkCopy instance
462521
*/
@@ -646,6 +705,7 @@ public void writeToServer(ISQLServerBulkData sourceData) throws SQLServerExcepti
646705
*/
647706
private void initializeDefaults() {
648707
columnMappings = new ArrayList<>();
708+
columnOrderHints = new ArrayList<>();
649709
destinationTableName = null;
650710
serverBulkData = null;
651711
sourceResultSet = null;
@@ -1493,6 +1553,7 @@ private String getDestTypeFromSrcType(int srcColIndx, int destColIndx,
14931553
private String createInsertBulkCommand(TDSWriter tdsWriter) throws SQLServerException {
14941554
StringBuilder bulkCmd = new StringBuilder();
14951555
List<String> bulkOptions = new ArrayList<>();
1556+
Set<String> destColumns = new HashSet<>();
14961557
String endColumn = " , ";
14971558
bulkCmd.append("INSERT BULK ").append(destinationTableName).append(" (");
14981559

@@ -1501,8 +1562,12 @@ private String createInsertBulkCommand(TDSWriter tdsWriter) throws SQLServerExce
15011562
endColumn = " ) ";
15021563
}
15031564
ColumnMapping colMapping = columnMappings.get(i);
1504-
String columnCollation = destColumnMetadata
1505-
.get(columnMappings.get(i).destinationColumnOrdinal).collationName;
1565+
1566+
BulkColumnMetaData columnMetaData = destColumnMetadata
1567+
.get(columnMappings.get(i).destinationColumnOrdinal);
1568+
destColumns.add(columnMetaData.columnName);
1569+
1570+
String columnCollation = columnMetaData.collationName;
15061571
String addCollate = "";
15071572

15081573
String destType = getDestTypeFromSrcType(colMapping.sourceColumnOrdinal,
@@ -1547,6 +1612,36 @@ private String createInsertBulkCommand(TDSWriter tdsWriter) throws SQLServerExce
15471612
bulkOptions.add("ALLOW_ENCRYPTED_VALUE_MODIFICATIONS");
15481613
}
15491614

1615+
if (0 < columnOrderHints.size()) {
1616+
StringBuilder orderHintText = new StringBuilder("ORDER(");
1617+
1618+
for (ColumnOrderHint columnOrderHint : columnOrderHints) {
1619+
String columnName = columnOrderHint.columnName;
1620+
1621+
if (!destColumns.contains(columnName)) {
1622+
MessageFormat form = new MessageFormat(
1623+
SQLServerException.getErrString("R_invalidColumn"));
1624+
Object[] msgArgs = { columnName };
1625+
throw new SQLServerException(form.format(msgArgs), SQLState.COL_NOT_FOUND,
1626+
DriverError.NOT_SET, null);
1627+
}
1628+
1629+
String sortOrderText = columnOrderHint.sortOrder == SQLServerSortOrder.DESCENDING ? "DESC" : "ASC";
1630+
1631+
if (columnName.contains("]")) {
1632+
String escapedColumnName = columnName.replaceAll("]", "]]");
1633+
orderHintText.append("[").append(escapedColumnName).append("] ").append(sortOrderText).append(", ");
1634+
} else {
1635+
orderHintText.append("[").append(columnName).append("] ").append(sortOrderText).append(", ");
1636+
}
1637+
}
1638+
1639+
orderHintText.setLength(orderHintText.length() - 2);
1640+
orderHintText.append(")");
1641+
1642+
bulkOptions.add(orderHintText.toString());
1643+
}
1644+
15501645
Iterator<String> it = bulkOptions.iterator();
15511646
if (it.hasNext()) {
15521647
bulkCmd.append(" with (");

0 commit comments

Comments
 (0)