Skip to content

Commit 4f784e0

Browse files
committed
Add tests for replace_ignore
1 parent 8332449 commit 4f784e0

1 file changed

Lines changed: 168 additions & 0 deletions

File tree

tests/test_asyncpg.py

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,3 +396,171 @@ class Test(ModelBase, table_name="test_upsert", primary_key="id"):
396396
assert result[0].created_at == "2023-01-04" # Should be updated
397397
assert result[0].name == "Alice Force"
398398
assert result[0].count == 20
399+
400+
401+
async def test_replace_multiple_with_replace_ignore(conn):
402+
"""Test replace_ignore ColumnInfo attribute."""
403+
404+
@dataclass(order=True)
405+
class Test(ModelBase, table_name="test", primary_key="id"):
406+
id: int
407+
name: str
408+
count: int
409+
# metadata field should be ignored during comparison
410+
metadata: Annotated[str, ColumnInfo(replace_ignore=True)]
411+
412+
await conn.execute(*Test.create_table_sql())
413+
414+
# Insert initial data
415+
data = [
416+
Test(1, "Alice", 10, "meta1"),
417+
Test(2, "Bob", 20, "meta2"),
418+
Test(3, "Charlie", 30, "meta3"),
419+
]
420+
await Test.insert_multiple(conn, data)
421+
422+
# Replace with same data but different metadata
423+
# Since metadata is ignored, no updates should happen
424+
new_data = [
425+
Test(1, "Alice", 10, "different_meta"),
426+
Test(2, "Bob", 20, "different_meta"),
427+
Test(3, "Charlie", 30, "different_meta"),
428+
]
429+
c, u, d = await Test.replace_multiple(conn, new_data, where=[])
430+
assert not c # No creates
431+
assert not u # No updates because metadata is ignored
432+
assert not d # No deletes
433+
434+
# Verify original metadata is preserved
435+
result = await Test.select(conn, order_by="id")
436+
assert result[0].metadata == "meta1"
437+
assert result[1].metadata == "meta2"
438+
assert result[2].metadata == "meta3"
439+
440+
# Now change a non-ignored field - should trigger update
441+
# The metadata will be updated too (it's only ignored for comparison)
442+
new_data[0] = Test(1, "Alice Updated", 10, "still_different")
443+
c, u, d = await Test.replace_multiple(conn, new_data, where=[])
444+
assert not c
445+
assert len(u) == 1 # Should update because name changed
446+
assert not d
447+
448+
# Verify update happened - metadata gets updated along with other fields
449+
result = await Test.select(conn, where=sql("id = 1"))
450+
assert result[0].name == "Alice Updated"
451+
assert result[0].metadata == "still_different" # Updated along with name
452+
453+
454+
async def test_replace_multiple_replace_ignore_with_force_update(conn):
455+
"""Test that force_update overrides replace_ignore."""
456+
457+
@dataclass(order=True)
458+
class Test(ModelBase, table_name="test", primary_key="id"):
459+
id: int
460+
name: str
461+
metadata: Annotated[str, ColumnInfo(replace_ignore=True)]
462+
463+
await conn.execute(*Test.create_table_sql())
464+
465+
# Insert initial data
466+
data = [Test(1, "Alice", "meta1"), Test(2, "Bob", "meta2")]
467+
await Test.insert_multiple(conn, data)
468+
469+
# Replace with different metadata, using force_update
470+
new_data = [Test(1, "Alice", "new_meta1"), Test(2, "Bob", "new_meta2")]
471+
c, u, d = await Test.replace_multiple(
472+
conn, new_data, where=[], force_update={"metadata"}
473+
)
474+
assert not c
475+
assert len(u) == 2 # Should update because force_update overrides replace_ignore
476+
assert not d
477+
478+
# Verify metadata was updated
479+
result = await Test.select(conn, order_by="id")
480+
assert result[0].metadata == "new_meta1"
481+
assert result[1].metadata == "new_meta2"
482+
483+
484+
async def test_replace_multiple_replace_ignore_with_insert_only(conn):
485+
"""Test interaction between replace_ignore and insert_only."""
486+
487+
@dataclass(order=True)
488+
class Test(ModelBase, table_name="test", primary_key="id"):
489+
id: int
490+
name: str
491+
# Both replace_ignore and insert_only
492+
created_at: Annotated[str, ColumnInfo(replace_ignore=True, insert_only=True)]
493+
# Only replace_ignore
494+
metadata: Annotated[str, ColumnInfo(replace_ignore=True)]
495+
496+
await conn.execute(*Test.create_table_sql())
497+
498+
# Insert initial data
499+
data = [Test(1, "Alice", "2023-01-01", "meta1")]
500+
await Test.insert_multiple(conn, data)
501+
502+
# Try to replace with different created_at and metadata
503+
new_data = [Test(1, "Alice", "2023-01-02", "meta2")]
504+
c, u, d = await Test.replace_multiple(conn, new_data, where=[])
505+
assert not c
506+
assert not u # No update because both fields are ignored
507+
assert not d
508+
509+
# Verify original values preserved
510+
result = await Test.select(conn)
511+
assert result[0].created_at == "2023-01-01"
512+
assert result[0].metadata == "meta1"
513+
514+
# Change name - should trigger update
515+
# created_at is preserved (insert_only), metadata is updated (only ignored for comparison)
516+
new_data = [Test(1, "Alice Updated", "2023-01-03", "meta3")]
517+
c, u, d = await Test.replace_multiple(conn, new_data, where=[])
518+
assert not c
519+
assert len(u) == 1
520+
assert not d
521+
522+
# Verify update happened
523+
result = await Test.select(conn)
524+
assert result[0].name == "Alice Updated"
525+
assert result[0].created_at == "2023-01-01" # Preserved (insert_only)
526+
assert result[0].metadata == "meta3" # Updated (only ignored for comparison)
527+
528+
529+
async def test_replace_multiple_replace_ignore_partial_match(conn):
530+
"""Test replace_ignore when only some records match."""
531+
532+
@dataclass(order=True)
533+
class Test(ModelBase, table_name="test", primary_key="id"):
534+
id: int
535+
category: str
536+
value: int
537+
metadata: Annotated[str, ColumnInfo(replace_ignore=True)]
538+
539+
await conn.execute(*Test.create_table_sql())
540+
541+
# Insert data with different categories
542+
data = [
543+
Test(1, "A", 10, "meta1"),
544+
Test(2, "A", 20, "meta2"),
545+
Test(3, "B", 30, "meta3"),
546+
]
547+
await Test.insert_multiple(conn, data)
548+
549+
# Replace only category A with different metadata
550+
new_data = [
551+
Test(1, "A", 10, "new_meta1"),
552+
Test(2, "A", 25, "new_meta2"), # value changed
553+
]
554+
c, u, d = await Test.replace_multiple(conn, new_data, where=sql("category = 'A'"))
555+
assert not c
556+
assert len(u) == 1 # Only id=2 should update (value changed)
557+
assert not d # Category B record not affected by where clause
558+
559+
# Verify results
560+
result = await Test.select(conn, order_by="id")
561+
assert len(result) == 3
562+
assert result[0].metadata == "meta1" # Unchanged (no update happened)
563+
assert result[0].value == 10
564+
assert result[1].metadata == "new_meta2" # Updated along with value
565+
assert result[1].value == 25 # Updated
566+
assert result[2] == data[2] # Category B unchanged

0 commit comments

Comments
 (0)