|
14 | 14 | from arcticdb.version_store import VersionedItem |
15 | 15 | from arcticdb_ext.storage import KeyType |
16 | 16 | import numpy as np |
17 | | -from arcticdb.exceptions import SchemaException, UserInputException, SortingException |
| 17 | +from arcticdb.exceptions import SchemaException, UserInputException, SortingException, StorageException |
18 | 18 | from typing import NamedTuple |
19 | 19 |
|
20 | 20 |
|
@@ -569,6 +569,66 @@ def test_merge_update_target_is_empty(self, lmdb_library, monkeypatch, merge_met |
569 | 569 | assert_vit_equals_except_data(merge_vit, read_vit) |
570 | 570 | assert_frame_equal(read_vit.data, expected) |
571 | 571 |
|
| 572 | + @pytest.mark.parametrize( |
| 573 | + "source", |
| 574 | + ( |
| 575 | + pd.DataFrame([], index=pd.DatetimeIndex([])), |
| 576 | + pd.DataFrame({"a": []}, index=pd.DatetimeIndex([])), |
| 577 | + pd.DataFrame({"a": [1]}, index=pd.DatetimeIndex([pd.Timestamp("2024-01-01")])), |
| 578 | + ), |
| 579 | + ) |
| 580 | + @pytest.mark.parametrize("upsert", (True, False)) |
| 581 | + def test_update_on_match_target_symbol_does_not_exist(self, lmdb_library, monkeypatch, source, upsert): |
| 582 | + # Model non-existing target after Library.update |
| 583 | + # There is an upsert parameter to control whether to create the index. If upsert=False exception is thrown. |
| 584 | + # Since we're doing a merge on non-existing data, I think it's logical to assume that nothing matches. If |
| 585 | + # upsert=True, we will create an empty dataframe with the same schema of the source. |
| 586 | + lib = lmdb_library |
| 587 | + |
| 588 | + if not upsert: |
| 589 | + monkeypatch.setattr(lib.__class__, "merge", raise_wrapper(StorageException), raising=False) |
| 590 | + with pytest.raises(StorageException): |
| 591 | + lib.merge( |
| 592 | + "sym", source, strategy=MergeStrategy(MergeAction.UPDATE, MergeAction.DO_NOTHING), upsert=upsert |
| 593 | + ) |
| 594 | + else: |
| 595 | + import datetime |
| 596 | + |
| 597 | + monkeypatch.setattr( |
| 598 | + lib.__class__, |
| 599 | + "merge", |
| 600 | + lambda *args, **kwargs: VersionedItem( |
| 601 | + symbol="sym", |
| 602 | + library=lmdb_library.name, |
| 603 | + data=None, |
| 604 | + version=0, |
| 605 | + metadata=None, |
| 606 | + host=lmdb_library._nvs.env, |
| 607 | + timestamp=pd.Timestamp(datetime.datetime.now()), |
| 608 | + ), |
| 609 | + raising=False, |
| 610 | + ) |
| 611 | + merge_vit = lib.merge( |
| 612 | + "sym", source, strategy=MergeStrategy(MergeAction.UPDATE, MergeAction.DO_NOTHING), upsert=upsert |
| 613 | + ) |
| 614 | + expected = pd.DataFrame({"a": []}, index=pd.DatetimeIndex([])) |
| 615 | + monkeypatch.setattr( |
| 616 | + lib, |
| 617 | + "read", |
| 618 | + lambda *args, **kwargs: VersionedItem( |
| 619 | + symbol=merge_vit.symbol, |
| 620 | + library=merge_vit.library, |
| 621 | + data=expected, |
| 622 | + version=merge_vit.version, |
| 623 | + metadata=merge_vit.metadata, |
| 624 | + host=merge_vit.host, |
| 625 | + timestamp=merge_vit.timestamp, |
| 626 | + ), |
| 627 | + ) |
| 628 | + read_vit = lib.read("sym") |
| 629 | + assert_vit_equals_except_data(merge_vit, read_vit) |
| 630 | + assert_frame_equal(read_vit.data, expected) |
| 631 | + |
572 | 632 | # ================================================================================================ |
573 | 633 | # ================================= TEST INSERT NOT MATCHED ====================================== |
574 | 634 | # ================================================================================================ |
@@ -991,6 +1051,63 @@ def test_update_and_insert_with_slicing(self, lmdb_library_factory, monkeypatch, |
991 | 1051 | assert len(lt.find_keys_for_symbol(KeyType.TABLE_INDEX, "sym")) == 2 |
992 | 1052 | assert len(lt.find_keys_for_symbol(KeyType.VERSION, "sym")) == 2 |
993 | 1053 |
|
| 1054 | + @pytest.mark.parametrize( |
| 1055 | + "source", |
| 1056 | + ( |
| 1057 | + pd.DataFrame([], index=pd.DatetimeIndex([])), |
| 1058 | + pd.DataFrame({"a": []}, index=pd.DatetimeIndex([])), |
| 1059 | + pd.DataFrame({"a": [1]}, index=pd.DatetimeIndex([pd.Timestamp("2024-01-01")])), |
| 1060 | + ), |
| 1061 | + ) |
| 1062 | + @pytest.mark.parametrize("upsert", (True, False)) |
| 1063 | + @pytest.mark.parametrize("strategy", (MergeStrategy("update", "insert"), MergeStrategy("do_nothing", "insert"))) |
| 1064 | + def test_insert_when_target_symbol_does_not_exist(self, lmdb_library, monkeypatch, source, upsert, strategy): |
| 1065 | + # Model non-existing target after Library.update |
| 1066 | + # There is an upsert parameter to control whether to create the index. If upsert=False exception is thrown. |
| 1067 | + # Since we're doing a merge on non-existing data, I think it's logical to assume that nothing matches. No |
| 1068 | + # updates are performed. The insert operation will insert the data into the newly created target symbol. |
| 1069 | + lib = lmdb_library |
| 1070 | + |
| 1071 | + if not upsert: |
| 1072 | + monkeypatch.setattr(lib.__class__, "merge", raise_wrapper(StorageException), raising=False) |
| 1073 | + with pytest.raises(StorageException): |
| 1074 | + lib.merge("sym", source, strategy=strategy, upsert=upsert) |
| 1075 | + else: |
| 1076 | + import datetime |
| 1077 | + |
| 1078 | + monkeypatch.setattr( |
| 1079 | + lib.__class__, |
| 1080 | + "merge", |
| 1081 | + lambda *args, **kwargs: VersionedItem( |
| 1082 | + symbol="sym", |
| 1083 | + library=lmdb_library.name, |
| 1084 | + data=None, |
| 1085 | + version=0, |
| 1086 | + metadata=None, |
| 1087 | + host=lmdb_library._nvs.env, |
| 1088 | + timestamp=pd.Timestamp(datetime.datetime.now()), |
| 1089 | + ), |
| 1090 | + raising=False, |
| 1091 | + ) |
| 1092 | + merge_vit = lib.merge("sym", source, strategy=strategy, upsert=upsert) |
| 1093 | + expected = source |
| 1094 | + monkeypatch.setattr( |
| 1095 | + lib, |
| 1096 | + "read", |
| 1097 | + lambda *args, **kwargs: VersionedItem( |
| 1098 | + symbol=merge_vit.symbol, |
| 1099 | + library=merge_vit.library, |
| 1100 | + data=expected, |
| 1101 | + version=merge_vit.version, |
| 1102 | + metadata=merge_vit.metadata, |
| 1103 | + host=merge_vit.host, |
| 1104 | + timestamp=merge_vit.timestamp, |
| 1105 | + ), |
| 1106 | + ) |
| 1107 | + read_vit = lib.read("sym") |
| 1108 | + assert_vit_equals_except_data(merge_vit, read_vit) |
| 1109 | + assert_frame_equal(read_vit.data, expected) |
| 1110 | + |
994 | 1111 | def test_update_and_insert_on_index_and_column(self, lmdb_library, monkeypatch): |
995 | 1112 | lib = lmdb_library |
996 | 1113 | target = pd.DataFrame( |
|
0 commit comments