django-bulk-hooks 0.2.29__tar.gz → 0.2.31__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of django-bulk-hooks might be problematic. Click here for more details.
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/PKG-INFO +1 -1
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/operations/bulk_executor.py +24 -33
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/pyproject.toml +1 -1
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/LICENSE +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/README.md +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/__init__.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/changeset.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/conditions.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/constants.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/context.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/decorators.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/dispatcher.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/enums.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/factory.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/handler.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/helpers.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/manager.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/models.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/operations/__init__.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/operations/analyzer.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/operations/coordinator.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/operations/mti_handler.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/operations/mti_plans.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/operations/record_classifier.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/queryset.py +0 -0
- {django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/registry.py +0 -0
{django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/operations/bulk_executor.py
RENAMED
|
@@ -77,9 +77,7 @@ class BulkExecutor:
|
|
|
77
77
|
existing_record_ids = set()
|
|
78
78
|
existing_pks_map = {}
|
|
79
79
|
if update_conflicts and unique_fields:
|
|
80
|
-
existing_record_ids, existing_pks_map = (
|
|
81
|
-
self.record_classifier.classify_for_upsert(objs, unique_fields)
|
|
82
|
-
)
|
|
80
|
+
existing_record_ids, existing_pks_map = self.record_classifier.classify_for_upsert(objs, unique_fields)
|
|
83
81
|
|
|
84
82
|
# Build execution plan with classification results
|
|
85
83
|
plan = self.mti_handler.build_create_plan(
|
|
@@ -173,13 +171,13 @@ class BulkExecutor:
|
|
|
173
171
|
def _execute_mti_create_plan(self, plan):
|
|
174
172
|
"""
|
|
175
173
|
Execute an MTI create plan.
|
|
176
|
-
|
|
174
|
+
|
|
177
175
|
This is where ALL database operations happen for MTI bulk_create.
|
|
178
176
|
Handles both new records (INSERT) and existing records (UPDATE) for upsert.
|
|
179
|
-
|
|
177
|
+
|
|
180
178
|
Args:
|
|
181
179
|
plan: MTICreatePlan object from MTIHandler
|
|
182
|
-
|
|
180
|
+
|
|
183
181
|
Returns:
|
|
184
182
|
List of created/updated objects with PKs assigned
|
|
185
183
|
"""
|
|
@@ -230,13 +228,8 @@ class BulkExecutor:
|
|
|
230
228
|
# Update existing parents
|
|
231
229
|
if existing_parents and parent_level.update_fields:
|
|
232
230
|
# Filter update fields to only those that exist in this parent model
|
|
233
|
-
parent_model_fields = {
|
|
234
|
-
|
|
235
|
-
}
|
|
236
|
-
filtered_update_fields = [
|
|
237
|
-
field for field in parent_level.update_fields
|
|
238
|
-
if field in parent_model_fields
|
|
239
|
-
]
|
|
231
|
+
parent_model_fields = {field.name for field in parent_level.model_class._meta.local_fields}
|
|
232
|
+
filtered_update_fields = [field for field in parent_level.update_fields if field in parent_model_fields]
|
|
240
233
|
|
|
241
234
|
if filtered_update_fields:
|
|
242
235
|
base_qs = BaseQuerySet(model=parent_level.model_class, using=self.queryset.db)
|
|
@@ -317,10 +310,7 @@ class BulkExecutor:
|
|
|
317
310
|
obj._state.db = self.queryset.db
|
|
318
311
|
|
|
319
312
|
if objs_without_pk:
|
|
320
|
-
filtered_fields = [
|
|
321
|
-
f for f in fields
|
|
322
|
-
if not isinstance(f, AutoField) and not f.primary_key
|
|
323
|
-
]
|
|
313
|
+
filtered_fields = [f for f in fields if not isinstance(f, AutoField) and not f.primary_key]
|
|
324
314
|
returned_columns = base_qs._batched_insert(
|
|
325
315
|
objs_without_pk,
|
|
326
316
|
filtered_fields,
|
|
@@ -341,13 +331,8 @@ class BulkExecutor:
|
|
|
341
331
|
# Step 3.5: Update existing child objects
|
|
342
332
|
if existing_child_objects and plan.update_fields:
|
|
343
333
|
# Filter update fields to only those that exist in the child model
|
|
344
|
-
child_model_fields = {
|
|
345
|
-
|
|
346
|
-
}
|
|
347
|
-
filtered_child_update_fields = [
|
|
348
|
-
field for field in plan.update_fields
|
|
349
|
-
if field in child_model_fields
|
|
350
|
-
]
|
|
334
|
+
child_model_fields = {field.name for field in plan.child_model._meta.local_fields}
|
|
335
|
+
filtered_child_update_fields = [field for field in plan.update_fields if field in child_model_fields]
|
|
351
336
|
|
|
352
337
|
if filtered_child_update_fields:
|
|
353
338
|
base_qs = BaseQuerySet(model=plan.child_model, using=self.queryset.db)
|
|
@@ -393,9 +378,11 @@ class BulkExecutor:
|
|
|
393
378
|
continue
|
|
394
379
|
|
|
395
380
|
# Copy auto_now_add, auto_now, and db_returning fields
|
|
396
|
-
if (
|
|
397
|
-
getattr(field, "
|
|
398
|
-
getattr(field, "
|
|
381
|
+
if (
|
|
382
|
+
getattr(field, "auto_now_add", False)
|
|
383
|
+
or getattr(field, "auto_now", False)
|
|
384
|
+
or getattr(field, "db_returning", False)
|
|
385
|
+
):
|
|
399
386
|
source_value = getattr(source_obj, field.name, None)
|
|
400
387
|
if source_value is not None:
|
|
401
388
|
setattr(orig_obj, field.name, source_value)
|
|
@@ -409,12 +396,12 @@ class BulkExecutor:
|
|
|
409
396
|
def _execute_mti_update_plan(self, plan):
|
|
410
397
|
"""
|
|
411
398
|
Execute an MTI update plan.
|
|
412
|
-
|
|
399
|
+
|
|
413
400
|
Updates each table in the inheritance chain using CASE/WHEN for bulk updates.
|
|
414
|
-
|
|
401
|
+
|
|
415
402
|
Args:
|
|
416
403
|
plan: MTIUpdatePlan object from MTIHandler
|
|
417
|
-
|
|
404
|
+
|
|
418
405
|
Returns:
|
|
419
406
|
Number of objects updated
|
|
420
407
|
"""
|
|
@@ -457,6 +444,10 @@ class BulkExecutor:
|
|
|
457
444
|
field = field_group.model_class._meta.get_field(field_name)
|
|
458
445
|
when_statements = []
|
|
459
446
|
|
|
447
|
+
# Determine the correct output field for type casting
|
|
448
|
+
# For ForeignKey fields, use the target field to ensure correct SQL types
|
|
449
|
+
case_output_field = field.target_field if isinstance(field, ForeignKey) else field
|
|
450
|
+
|
|
460
451
|
for pk, obj in zip(root_pks, plan.objects):
|
|
461
452
|
obj_pk = getattr(obj, "pk", None) or getattr(obj, "id", None)
|
|
462
453
|
if obj_pk is None:
|
|
@@ -464,16 +455,16 @@ class BulkExecutor:
|
|
|
464
455
|
|
|
465
456
|
# Get the field value - handle ForeignKey fields specially
|
|
466
457
|
value = getattr(obj, field.attname, None) if isinstance(field, ForeignKey) else getattr(obj, field_name)
|
|
467
|
-
|
|
458
|
+
|
|
468
459
|
when_statements.append(
|
|
469
460
|
When(
|
|
470
461
|
**{field_group.filter_field: pk},
|
|
471
|
-
then=Value(value, output_field=
|
|
462
|
+
then=Value(value, output_field=case_output_field),
|
|
472
463
|
),
|
|
473
464
|
)
|
|
474
465
|
|
|
475
466
|
if when_statements:
|
|
476
|
-
case_statements[field_name] = Case(*when_statements, output_field=
|
|
467
|
+
case_statements[field_name] = Case(*when_statements, output_field=case_output_field)
|
|
477
468
|
|
|
478
469
|
# Execute bulk update
|
|
479
470
|
if case_statements:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/operations/__init__.py
RENAMED
|
File without changes
|
{django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/operations/analyzer.py
RENAMED
|
File without changes
|
{django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/operations/coordinator.py
RENAMED
|
File without changes
|
{django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/operations/mti_handler.py
RENAMED
|
File without changes
|
{django_bulk_hooks-0.2.29 → django_bulk_hooks-0.2.31}/django_bulk_hooks/operations/mti_plans.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|