Skip to content

Add order Hints for Bulk Copy operations #2472

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

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
442c816
Add order Hints for Bulk Copy operations (#1481)
mobilebilly Jul 7, 2024
1629062
Correct the wrong javadoc in SQLServerBulkCopy.addColumnOrderHint
mobilebilly Jul 7, 2024
8da2481
Escape the column name in the order hints with square bracket correctly
mobilebilly Jul 7, 2024
e35d099
Add overload addColumn which accept custom column name
mobilebilly Jul 7, 2024
dcead0d
Escape the Close escape character correctly in the escapeIdentifier m…
mobilebilly Jul 7, 2024
e3c765b
Add unit test cases to the column order hints enhancement
mobilebilly Jul 7, 2024
31b5d00
Merge branch 'microsoft:main' into main
mobilebilly Jul 10, 2024
e6a3005
Merge branch 'microsoft:main' into main
mobilebilly Aug 2, 2024
9b195c2
Merge branch 'microsoft:main' into main
mobilebilly Aug 24, 2024
f8827a2
Merge branch 'microsoft:main' into main
mobilebilly Aug 29, 2024
c4777de
Merge branch 'microsoft:main' into main
mobilebilly Sep 11, 2024
86e8f98
Merge branch 'microsoft:main' into main
mobilebilly Sep 24, 2024
971c2ec
Merge branch 'microsoft:main' into main
mobilebilly Sep 30, 2024
433da04
Merge branch 'microsoft:main' into main
mobilebilly Nov 9, 2024
761060b
Merge branch 'microsoft:main' into main
mobilebilly Nov 16, 2024
c071e5f
Merge branch 'microsoft:main' into main
mobilebilly Dec 10, 2024
a3cb495
Merge branch 'microsoft:main' into main
mobilebilly Jan 5, 2025
13c683e
Merge branch 'microsoft:main' into main
mobilebilly Jan 18, 2025
fab83aa
Merge branch 'microsoft:main' into main
mobilebilly Feb 3, 2025
87a0bd5
Merge branch 'microsoft:main' into main
mobilebilly Feb 19, 2025
ad6b8a4
Merge branch 'microsoft:main' into main
mobilebilly Feb 23, 2025
c8e872a
Merge branch 'microsoft:main' into main
mobilebilly Mar 4, 2025
02d7758
Merge branch 'microsoft:main' into main
mobilebilly Mar 8, 2025
39cc70e
Merge branch 'microsoft:main' into main
mobilebilly Mar 26, 2025
0c3fe65
Merge branch 'microsoft:main' into main
mobilebilly Apr 3, 2025
45d9060
Merge branch 'microsoft:main' into main
mobilebilly Apr 28, 2025
45daa81
Merge branch 'microsoft:main' into main
mobilebilly May 18, 2025
bf03f21
Merge branch 'microsoft:main' into main
mobilebilly May 31, 2025
11fd746
Merge branch 'microsoft:main' into main
mobilebilly Jun 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 97 additions & 2 deletions src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
Expand Down Expand Up @@ -110,6 +111,22 @@ private class ColumnMapping implements Serializable {
}
}

private class ColumnOrderHint implements Serializable {
/**
* Always update serialVersionUID when prompted.
*/
private static final long serialVersionUID = 6132627333120344137L;

String columnName = null;

SQLServerSortOrder sortOrder;

ColumnOrderHint(String columnName, SQLServerSortOrder sortOrder) {
this.columnName = columnName;
this.sortOrder = sortOrder;
}
}

/**
* Class name for logging.
*/
Expand All @@ -135,6 +152,11 @@ private class ColumnMapping implements Serializable {
*/
private List<ColumnMapping> columnMappings;

/**
* Column order hints describe the sort order of columns in the clustered index of the destination
*/
private List<ColumnOrderHint> columnOrderHints;

/**
* Flag if SQLServerBulkCopy owns the connection and should close it when Close is called
*/
Expand Down Expand Up @@ -456,6 +478,43 @@ public void clearColumnMappings() {
loggerExternal.exiting(loggerClassName, "clearColumnMappings");
}

/**
* Adds a new column order hint, specify the column name and sort order
*
* @param columnName
* Column name.
* @param sortOrder
* Column sort order.
* @throws SQLServerException
* If the column order hint is invalid
*/
public void addColumnOrderHint(String columnName, SQLServerSortOrder sortOrder) throws SQLServerException {
if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) {
loggerExternal.entering(loggerClassName, "addColumnOrderHint",
new Object[] {columnName, sortOrder});
}

if (null == columnName || columnName.isEmpty()) {
throwInvalidArgument("columnName");
} else if (null == sortOrder || SQLServerSortOrder.UNSPECIFIED == sortOrder) {
throwInvalidArgument("sortOrder");
}
columnOrderHints.add(new ColumnOrderHint(columnName, sortOrder));

loggerExternal.exiting(loggerClassName, "addColumnOrderHint");
}

/**
* Clears the contents of the column order hints
*/
public void clearColumnOrderHints() {
loggerExternal.entering(loggerClassName, "clearColumnOrderHints");

columnOrderHints.clear();

loggerExternal.exiting(loggerClassName, "clearColumnOrderHints");
}

/**
* Closes the SQLServerBulkCopy instance
*/
Expand Down Expand Up @@ -645,6 +704,7 @@ public void writeToServer(ISQLServerBulkData sourceData) throws SQLServerExcepti
*/
private void initializeDefaults() {
columnMappings = new ArrayList<>();
columnOrderHints = new ArrayList<>();
destinationTableName = null;
serverBulkData = null;
sourceResultSet = null;
Expand Down Expand Up @@ -1479,6 +1539,7 @@ private String getDestTypeFromSrcType(int srcColIndx, int destColIndx,
private String createInsertBulkCommand(TDSWriter tdsWriter) throws SQLServerException {
StringBuilder bulkCmd = new StringBuilder();
List<String> bulkOptions = new ArrayList<>();
Set<String> destColumns = new HashSet<>();
String endColumn = " , ";
bulkCmd.append("INSERT BULK ").append(destinationTableName).append(" (");

Expand All @@ -1487,8 +1548,12 @@ private String createInsertBulkCommand(TDSWriter tdsWriter) throws SQLServerExce
endColumn = " ) ";
}
ColumnMapping colMapping = columnMappings.get(i);
String columnCollation = destColumnMetadata
.get(columnMappings.get(i).destinationColumnOrdinal).collationName;

BulkColumnMetaData columnMetaData = destColumnMetadata
.get(columnMappings.get(i).destinationColumnOrdinal);
destColumns.add(columnMetaData.columnName);

String columnCollation = columnMetaData.collationName;
String addCollate = "";

String destType = getDestTypeFromSrcType(colMapping.sourceColumnOrdinal,
Expand Down Expand Up @@ -1533,6 +1598,36 @@ private String createInsertBulkCommand(TDSWriter tdsWriter) throws SQLServerExce
bulkOptions.add("ALLOW_ENCRYPTED_VALUE_MODIFICATIONS");
}

if (0 < columnOrderHints.size()) {
StringBuilder orderHintText = new StringBuilder("ORDER(");

for (ColumnOrderHint columnOrderHint : columnOrderHints) {
String columnName = columnOrderHint.columnName;

if (!destColumns.contains(columnName)) {
MessageFormat form = new MessageFormat(
SQLServerException.getErrString("R_invalidColumn"));
Object[] msgArgs = { columnName };
throw new SQLServerException(form.format(msgArgs), SQLState.COL_NOT_FOUND,
DriverError.NOT_SET, null);
}

String sortOrderText = columnOrderHint.sortOrder == SQLServerSortOrder.DESCENDING ? "DESC" : "ASC";

if (columnName.contains("]")) {
String escapedColumnName = columnName.replaceAll("]", "]]");
orderHintText.append("[").append(escapedColumnName).append("] ").append(sortOrderText).append(", ");
} else {
orderHintText.append("[").append(columnName).append("] ").append(sortOrderText).append(", ");
}
}

orderHintText.setLength(orderHintText.length() - 2);
orderHintText.append(")");

bulkOptions.add(orderHintText.toString());
}

Iterator<String> it = bulkOptions.iterator();
if (it.hasNext()) {
bulkCmd.append(" with (");
Expand Down
Loading