def test_in(self): res = bulk_update(TestModel, [{ 'id': [1, 2, 3], 'name': '1' }, { 'id': [4, 5, 6], 'name': '2' }], key_fields_ops=['in']) self.assertEqual(6, res) for pk, name, int_field in TestModel.objects.all().order_by('id').values_list('id', 'name', 'int_field'): if pk in {1, 2, 3}: self.assertEqual('1', name) elif pk in {4, 5, 6}: self.assertEqual('2', name) else: self.assertEqual('test%d' % pk, name) self.assertEqual(pk, int_field) # Test not id field res = bulk_update(TestModel, [{ 'int_field': 1, 'name': ['1'] }, { 'int_field': 2, 'name': ['2'] }], key_fields='name', key_fields_ops=['in']) self.assertEqual(6, res) for pk, name, int_field in TestModel.objects.all().order_by('id').values_list('id', 'name', 'int_field'): if pk in {1, 2, 3}: self.assertEqual(1, int_field) elif pk in {4, 5, 6}: self.assertEqual(2, int_field) else: self.assertEqual('test%d' % pk, name)
def test_batch(self): with self.assertRaises(TypeError): bulk_update(TestModel, [{ 'id': 1, 'name': 'test1' }], batch_size='abc') with self.assertRaises(ValueError): bulk_update(TestModel, [{'id': 1, 'name': 'test1'}], batch_size=-2) with self.assertRaises(TypeError): bulk_update(TestModel, [{ 'id': 1, 'name': 'test1' }], batch_size=2.5) with self.assertRaises(TypeError): bulk_update(TestModel, [{ 'id': 1, 'name': 'test1' }], batch_size=1, batch_delay='abc') with self.assertRaises(ValueError): bulk_update(TestModel, [{ 'id': 1, 'name': 'test1' }], batch_size=1, batch_delay=-2)
def test_is_null(self): # Create model who has null value TestModel.objects.create(id=10) # IS NULL testing res = bulk_update(TestModel, [{ 'name': 'is_null', 'int_field': True }], key_fields_ops=['is_null'], key_fields='int_field') self.assertEqual(1, res) for pk, name, int_field in TestModel.objects.all().order_by('id').values_list('id', 'name', 'int_field'): if pk > 9: self.assertEqual('is_null', name) self.assertIsNone(int_field) else: self.assertEqual('test%d' % pk, name) self.assertEqual(pk, int_field) # IS NOT NULL testing res = bulk_update(TestModel, [{ 'name': 'is_not_null', 'int_field': False }], key_fields_ops=['is_null'], key_fields='int_field') self.assertEqual(9, res) for pk, name, int_field in TestModel.objects.all().order_by('id').values_list('id', 'name', 'int_field'): if pk > 9: self.assertEqual('is_null', name) self.assertIsNone(int_field) else: self.assertEqual('is_not_null', name) self.assertEqual(pk, int_field)
def test_example(self): # Skip bulk_create and bulk_update_or_create sections (tested in other test) TestModel.objects.bulk_create([TestModel(pk=i, name="item%d" % i, int_field=1) for i in range(1, 4)]) # Update by id field updated = bulk_update(TestModel, [{ "id": 1, "name": "updated1", }, { "id": 2, "name": "updated2" }]) self.assertEqual(2, updated) res = bulk_update(TestModel, [{ "id": 1, "name": "updated1", }, { "id": 2, "name": "updated2" }], returning=('id', 'name', 'int_field')) from django_pg_returning import ReturningQuerySet self.assertIsInstance(res, ReturningQuerySet) self.assertSetEqual({ (1, "updated1", 1), (2, "updated2", 1) }, set(res.values_list('id', 'name', 'int_field'))) updated = bulk_update(TestModel, { "updated1": { "int_field": 2 }, "updated2": { "int_field": 3 } }, key_fields="name") self.assertEqual(2, updated) self.assertListEqual([ {"id": 1, "name": "updated1", "int_field": 2}, {"id": 2, "name": "updated2", "int_field": 3}, {"id": 3, "name": "item3", "int_field": 1} ], list(TestModel.objects.all().order_by("id").values("id", "name", "int_field"))) updated = bulk_update(TestModel, { (2, 3): { "int_field": 3, "name": "incr" } }, key_fields=['id', 'int_field'], key_fields_ops={'int_field': '<', 'id': 'gte'}, set_functions={'int_field': '+'}) self.assertEqual(1, updated) self.assertListEqual([ {"id": 1, "name": "updated1", "int_field": 2}, {"id": 2, "name": "updated2", "int_field": 3}, {"id": 3, "name": "incr", "int_field": 4} ], list(TestModel.objects.all().order_by("id").values("id", "name", "int_field")))
def test_union_array(self): for i in range(1, 5): res = bulk_update(TestModel, [{'id': 1, 'array_field': [1]}, {'id': 2, 'array_field': [2]}, {'id': 3, 'array_field': [i]}, {'id': 4, 'array_field': []}], set_functions={'array_field': 'union'}) self._test_union_array(i, res)
def test_concat_hstore(self): for i in range(1, 5): res = bulk_update(TestModel, [{'id': 1, 'hstore_field': {i: 1}}, {'id': 2, 'hstore_field': {i: 2}}, {'id': 3, 'hstore_field': {i: 3}}, {'id': 4, 'hstore_field': {}}], set_functions={'hstore_field': '||'}) self._test_concat_dict(i, res, 'hstore_field', val_as_str=True)
def test_array_remove(self): TestModel.objects.all().update(array_field=[1, 2, 2]) res = bulk_update(TestModel, [{ 'id': 1, 'array_field': 1 }, { 'id': 2, 'array_field': 2 }, { 'id': 3, 'array_field': 3 }], set_functions={'array_field': 'array_remove'}) self.assertEqual(3, res) for pk, array_field in TestModel.objects.all().order_by( 'id').values_list('id', 'array_field'): if pk == 1: self.assertListEqual([2, 2], array_field) elif pk == 2: self.assertListEqual([1], array_field) elif pk == 3: self.assertListEqual([1, 2, 2], array_field)
def test_eq_not_null(self): # Test, that NULL value in db will be NULL after update TestModel.objects.filter(pk=3).update(int_field=None) res = bulk_update(TestModel, [{ 'id': 1, 'int_field': 2 }, { 'id': 2, 'int_field': 3 }, { 'id': 3, 'int_field': None }, { 'id': 4, 'int_field': None }], set_functions={'int_field': 'eq_not_null'}) self.assertEqual(4, res) for pk, name, int_field in TestModel.objects.all().order_by( 'id').values_list('id', 'name', 'int_field'): if pk in {1, 2}: self.assertEqual(pk, int_field - 1) elif pk == 3: self.assertIsNone(int_field) elif pk == 4: self.assertEqual(pk, int_field) else: self.assertEqual('test%d' % pk, name) self.assertEqual('test%d' % pk, name)
def test_concat_jsonb(self): for i in range(1, 5): res = bulk_update(TestModel, [{'id': 1, 'json_field': {i: 1}}, {'id': 2, 'json_field': {i: 2}}, {'id': 3, 'json_field': {i: 3}}, {'id': 4, 'json_field': {}}], set_functions={'json_field': '||'}) self._test_concat_dict(i, res, 'json_field')
def test_using(self): res = bulk_update(TestModel, [{ 'id': 1, 'name': 'bulk_update_1' }, { 'id': 5, 'name': 'bulk_update_5' }, { 'id': 8, 'name': 'bulk_update_8' }], using='secondary') self.assertEqual(3, res) for pk, name, int_field in TestModel.objects.all().using('secondary').order_by('id').\ values_list('id', 'name', 'int_field'): if pk in {1, 5, 8}: self.assertEqual('bulk_update_%d' % pk, name) else: self.assertEqual('test%d' % pk, name) self.assertEqual(pk, int_field) for pk, name, int_field in TestModel.objects.all().using('default').order_by('id').\ values_list('id', 'name', 'int_field'): self.assertEqual('test%d' % pk, name) self.assertEqual(pk, int_field)
def test_empty(self): res = bulk_update(TestModel, []) self.assertEqual(0, res) for pk, name, int_field in TestModel.objects.all().order_by( 'id').values_list('id', 'name', 'int_field'): self.assertEqual('test%d' % pk, name) self.assertEqual(pk, int_field)
def test_returning(self): res = bulk_update(TestModel, [{ 'id': 1, 'name': 'bulk_update_1' }, { 'id': 5, 'name': 'bulk_update_5' }, { 'id': 8, 'name': 'bulk_update_8' }], returning=('id', 'name', 'int_field')) from django_pg_returning import ReturningQuerySet self.assertIsInstance(res, ReturningQuerySet) self.assertSetEqual({ (1, 'bulk_update_1', 1), (5, 'bulk_update_5', 5), (8, 'bulk_update_8', 8) }, set(res.values_list('id', 'name', 'int_field'))) for pk, name, int_field in TestModel.objects.all().order_by('id').values_list('id', 'name', 'int_field'): if pk in {1, 5, 8}: self.assertEqual('bulk_update_%d' % pk, name) else: self.assertEqual('test%d' % pk, name) self.assertEqual(pk, int_field)
def test_quoted_table_name(self): # Test for https://github.com/M1ha-Shvn/django-pg-bulk-update/issues/63 self.assertEqual( 1, bulk_update(TestModelWithSchema, [{ 'id': 1, 'name': 'abc' }]))
def test_returning_empty(self): res = bulk_update(TestModel, [{ 'id': 100, 'name': 'not_exist' }], returning='id') from django_pg_returning import ReturningQuerySet self.assertIsInstance(res, ReturningQuerySet) self.assertEqual(0, res.count())
def test_returning_all_m2m(self): res = bulk_update(RelationModel, [{ 'id': 1, 'int_field': 2 }], returning='*') from django_pg_returning import ReturningQuerySet self.assertIsInstance(res, ReturningQuerySet) self.assertSetEqual({(1, 2, 1, 1)}, set(res.values_list('id', 'int_field', 'fk_id', 'o2o_id')))
def test_between(self): res = bulk_update(TestModel, [{ 'id': [2, 5], 'name': '1' }], key_fields_ops=['between']) self.assertEqual(4, res) for pk, name, int_field in TestModel.objects.all().order_by('id').values_list('id', 'name', 'int_field'): if pk in {2, 3, 4, 5}: self.assertEqual('1', name) else: self.assertEqual('test%d' % pk, name) self.assertEqual(pk, int_field)
def test_not_equal(self): res = bulk_update(TestModel, [{ 'id': 1, 'name': '1' }], key_fields_ops=['!eq']) self.assertEqual(8, res) for pk, name, int_field in TestModel.objects.all().order_by('id').values_list('id', 'name', 'int_field'): if pk != 1: self.assertEqual('1', name) else: self.assertEqual('test%d' % pk, name) self.assertEqual(pk, int_field)
def test_gte(self): res = bulk_update(TestModel, [{ 'id': 5, 'name': '1' }], key_fields_ops=['>=']) self.assertEqual(5, res) for pk, name, int_field in TestModel.objects.all().order_by('id').values_list('id', 'name', 'int_field'): if pk in {5, 6, 7, 8, 9}: self.assertEqual('1', name) else: self.assertEqual('test%d' % pk, name) self.assertEqual(pk, int_field)
def test_batch(self): res = bulk_update(TestModel, [{ 'id': 1, 'name': 'bulk_update_1' }, { 'id': 5, 'name': 'bulk_update_5' }, { 'id': 8, 'name': 'bulk_update_8' }], batch_size=1) self.assertEqual(3, res) for pk, name, int_field in TestModel.objects.all().order_by('id').values_list('id', 'name', 'int_field'): if pk in {1, 5, 8}: self.assertEqual('bulk_update_%d' % pk, name) else: self.assertEqual('test%d' % pk, name) self.assertEqual(pk, int_field) # Test for empty values correct res = bulk_update(TestModel, [], batch_size=10) self.assertEqual(0, res)
def test_auto_now(self): res = bulk_update(AutoNowModel, [{ 'id': 1, 'checked': datetime(2020, 1, 2, 0, 0, 0, tzinfo=pytz.utc) }]) self.assertEqual(1, res) self.assertEqual(1, AutoNowModel.objects.all().count()) instance = AutoNowModel.objects.get() self.assertEqual(datetime(2019, 1, 1, tzinfo=pytz.utc), instance.created) self.assertEqual(instance.updated, datetime.now(pytz.utc).date()) self.assertEqual(datetime(2020, 1, 2, 0, 0, 0, tzinfo=pytz.utc), instance.checked)
def test_auto_now_respects_override(self): # Now check to make sure we can explicitly set values # (requires passing set functions) bulk_update( AutoNowModel, [{ 'id': 1, 'created': datetime(2011, 1, 2, 0, 0, 0, tzinfo=tz_utc), 'updated': date(2011, 1, 3), 'checked': datetime(2011, 1, 4, 0, 0, 0, tzinfo=tz_utc), }], set_functions={ "created": "eq", "updated": "eq" }) instance = AutoNowModel.objects.get() self.assertEqual(datetime(2011, 1, 2, 0, 0, 0, tzinfo=tz_utc), instance.created) self.assertEqual(date(2011, 1, 3), instance.updated) self.assertEqual(datetime(2011, 1, 4, 0, 0, 0, tzinfo=tz_utc), instance.checked)
def test_array(self): res = bulk_update(TestModel, [{'id': 1, 'array_field': [1]}, {'id': 2, 'array_field': [2]}, {'id': 3, 'array_field': [3]}, {'id': 4, 'array_field': []}]) self.assertEqual(4, res) for pk, name, array_field in TestModel.objects.all().order_by('id').values_list('id', 'name', 'array_field'): if pk in {1, 2, 3}: self.assertListEqual([pk], array_field) elif pk == 4: self.assertListEqual([], array_field) else: self.assertIsNone(array_field) self.assertEqual('test%d' % pk, name)
def test_upper_case(self): res = bulk_update(UpperCaseModel, [{ 'id': 1, 'UpperCaseName': 'BulkUpdate1' }, { 'id': 3, 'UpperCaseName': 'BulkUpdate3' }]) self.assertEqual(2, res) for pk, name in UpperCaseModel.objects.all().order_by('id').values_list('id', 'UpperCaseName'): if pk in {1, 3}: self.assertEqual('BulkUpdate%d' % pk, name) else: self.assertEqual('test%d' % pk, name)
def test_update(self): res = bulk_update(UUIDFieldPrimaryModel, [{ 'key_field': 1, 'char_field': '5' }, { 'key_field': 2, 'char_field': '6' }], key_fields=['key_field']) self.assertEqual(1, res) instance = UUIDFieldPrimaryModel.objects.get() self.assertEqual(UUID("09ddba14-4acb-4fff-9381-7f7b253181e7"), instance.pk) self.assertEqual('5', instance.char_field)
def test_key_fields(self): values = [{'id': 1, 'name': 'bulk_update_1'}] self.assertEqual(1, bulk_update(TestModel, values)) self.assertEqual(1, bulk_update(TestModel, values, key_fields='id')) self.assertEqual(1, bulk_update(TestModel, values, key_fields=['id'])) self.assertEqual( 1, bulk_update(TestModel, values, key_fields=['id', 'name'])) self.assertEqual(1, bulk_update(TestModel, values, key_fields='name')) self.assertEqual(1, bulk_update(TestModel, values, key_fields=['name']))
def test_using(self): values = [{'id': 1, 'name': 'bulk_update_1'}] self.assertEqual(1, bulk_update(TestModel, values)) self.assertEqual(1, bulk_update(TestModel, values, using='default')) with self.assertRaises(ValueError): bulk_update(TestModel, values, using='invalid') with self.assertRaises(TypeError): bulk_update(TestModel, values, using=123)
def test_hstore(self): res = bulk_update(TestModel, [{'id': 1, 'hstore_field': {'test': '1'}}, {'id': 2, 'hstore_field': {'test': '2'}}, {'id': 3, 'hstore_field': {'test': '3'}}, {'id': 4, 'hstore_field': {}}, {'id': 5, 'hstore_field': {'single': "'", "multi": '"'}}]) self.assertEqual(5, res) for item in TestModel.objects.all().order_by('id'): if item.pk in {1, 2, 3}: self.assertDictEqual({'test': str(item.pk)}, item.hstore_field) elif item.pk == 4: self.assertDictEqual({}, item.hstore_field) elif item.pk == 5: self.assertDictEqual({'single': "'", "multi": '"'}, item.hstore_field) else: self.assertIsNone(item.hstore_field) self.assertEqual('test%d' % item.pk, item.name)
def test_jsonb(self): res = bulk_update(TestModel, [{'id': 1, 'json_field': {'test': '1'}}, {'id': 2, 'json_field': {'test': '2'}}, {'id': 3, 'json_field': {'test': '3'}}, {'id': 4, 'json_field': {}}, {'id': 5, 'json_field': {'single': "'", "multi": '"'}}]) self.assertEqual(5, res) for pk, name, json_field in TestModel.objects.all().order_by('id').values_list('id', 'name', 'json_field'): if pk in {1, 2, 3}: self.assertDictEqual({'test': str(pk)}, json_field) elif pk == 4: self.assertDictEqual({}, json_field) elif pk == 5: self.assertDictEqual({'single': "'", "multi": '"'}, json_field) else: self.assertIsNone(json_field) self.assertEqual('test%d' % pk, name)
def test_not_in(self): res = bulk_update(TestModel, [{ 'id': list(range(4, 10)), 'name': '1' }, { 'id': list(range(7, 10)) + list(range(1, 4)), 'name': '2' }], key_fields_ops=['!in']) self.assertEqual(6, res) for pk, name, int_field in TestModel.objects.all().order_by('id').values_list('id', 'name', 'int_field'): if pk in {1, 2, 3}: self.assertEqual('1', name) elif pk in {4, 5, 6}: self.assertEqual('2', name) else: self.assertEqual('test%d' % pk, name) self.assertEqual(pk, int_field)
def test_quotes(self): res = bulk_update(TestModel, [{ 'id': 1, 'name': '\'' }, { 'id': 5, 'name': '"' }]) self.assertEqual(2, res) for pk, name, int_field in TestModel.objects.all().order_by('id').values_list('id', 'name', 'int_field'): if pk == 1: self.assertEqual('\'', name) elif pk == 5: self.assertEqual('"', name) else: self.assertEqual('test%d' % pk, name) self.assertEqual(pk, int_field)