Skip to content

Commit fa2eab4

Browse files
committed
feat(bulkcopy): Replace **kwargs with explicit parameters for better IDE discoverability
- All options now explicit in function signature - Pass params directly to pycore (no kwargs dict conversion) - Matches mssql-tds explicit params API Based on community feedback from discussion #414
1 parent f229052 commit fa2eab4

File tree

1 file changed

+49
-17
lines changed

1 file changed

+49
-17
lines changed

mssql_python/cursor.py

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2452,7 +2452,18 @@ def nextset(self) -> Union[bool, None]:
24522452
return True
24532453

24542454
def _bulkcopy(
2455-
self, table_name: str, data: Iterable[Union[Tuple, List]], **kwargs
2455+
self,
2456+
table_name: str,
2457+
data: Iterable[Union[Tuple, List]],
2458+
batch_size: Optional[int] = None,
2459+
timeout: Optional[int] = 30,
2460+
column_mappings: Optional[List[Tuple[Union[str, int], str]]] = None,
2461+
keep_identity: Optional[bool] = None,
2462+
check_constraints: Optional[bool] = None,
2463+
table_lock: Optional[bool] = None,
2464+
keep_nulls: Optional[bool] = None,
2465+
fire_triggers: Optional[bool] = None,
2466+
use_internal_transaction: Optional[bool] = None,
24562467
): # pragma: no cover
24572468
"""
24582469
Perform bulk copy operation for high-performance data loading.
@@ -2471,20 +2482,33 @@ def _bulkcopy(
24712482
- The number of values in each row must match the number of columns
24722483
in the target table
24732484
2474-
**kwargs: Additional bulk copy options.
2485+
batch_size: Number of rows to send per batch. Default uses server optimal.
2486+
2487+
timeout: Operation timeout in seconds. Default is 30.
2488+
2489+
column_mappings: Maps source data columns to target table column names.
2490+
Each tuple is (source, target_column_name) where:
2491+
- source: Column name (str) or 0-based index (int) in the source data
2492+
- target_column_name: Name of the target column in the database table
2493+
2494+
When omitted: Columns are mapped by ordinal position (first data
2495+
column → first table column, second → second, etc.)
2496+
2497+
When specified: Only the mapped columns are inserted; unmapped
2498+
source columns are ignored, and unmapped target columns must
2499+
have default values or allow NULL.
2500+
2501+
keep_identity: Preserve identity values from source data.
24752502
2476-
column_mappings (List[Tuple[int, str]], optional):
2477-
Maps source data column indices to target table column names.
2478-
Each tuple is (source_index, target_column_name) where:
2479-
- source_index: 0-based index of the column in the source data
2480-
- target_column_name: Name of the target column in the database table
2503+
check_constraints: Check constraints during bulk copy.
24812504
2482-
When omitted: Columns are mapped by ordinal position (first data
2483-
column → first table column, second → second, etc.)
2505+
table_lock: Use table-level lock instead of row-level locks.
24842506
2485-
When specified: Only the mapped columns are inserted; unmapped
2486-
source columns are ignored, and unmapped target columns must
2487-
have default values or allow NULL.
2507+
keep_nulls: Preserve null values instead of using default values.
2508+
2509+
fire_triggers: Fire insert triggers on the target table.
2510+
2511+
use_internal_transaction: Use an internal transaction for each batch.
24882512
24892513
Returns:
24902514
Dictionary with bulk copy results including:
@@ -2523,10 +2547,6 @@ def _bulkcopy(
25232547
f"data must be an iterable of tuples or lists, got non-iterable {type(data).__name__}"
25242548
)
25252549

2526-
# Extract and validate kwargs with defaults
2527-
batch_size = kwargs.get("batch_size", None)
2528-
timeout = kwargs.get("timeout", 30)
2529-
25302550
# Validate batch_size type and value (only if explicitly provided)
25312551
if batch_size is not None:
25322552
if not isinstance(batch_size, (int, float)):
@@ -2599,7 +2619,19 @@ def _bulkcopy(
25992619
pycore_connection = mssql_py_core.PyCoreConnection(pycore_context)
26002620
pycore_cursor = pycore_connection.cursor()
26012621

2602-
result = pycore_cursor.bulkcopy(table_name, iter(data), **kwargs)
2622+
result = pycore_cursor.bulkcopy(
2623+
table_name,
2624+
iter(data),
2625+
batch_size=batch_size,
2626+
timeout=timeout,
2627+
column_mappings=column_mappings,
2628+
keep_identity=keep_identity,
2629+
check_constraints=check_constraints,
2630+
table_lock=table_lock,
2631+
keep_nulls=keep_nulls,
2632+
fire_triggers=fire_triggers,
2633+
use_internal_transaction=use_internal_transaction,
2634+
)
26032635

26042636
return result
26052637

0 commit comments

Comments
 (0)