Skip to content

Commit 2e55b66

Browse files
committed
Merge when the target symbol does not exist
1 parent 110ff25 commit 2e55b66

File tree

1 file changed

+118
-1
lines changed

1 file changed

+118
-1
lines changed

python/tests/unit/arcticdb/version_store/test_merge.py

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from arcticdb.version_store import VersionedItem
1515
from arcticdb_ext.storage import KeyType
1616
import numpy as np
17-
from arcticdb.exceptions import SchemaException, UserInputException, SortingException
17+
from arcticdb.exceptions import SchemaException, UserInputException, SortingException, StorageException
1818
from typing import NamedTuple
1919

2020

@@ -569,6 +569,66 @@ def test_merge_update_target_is_empty(self, lmdb_library, monkeypatch, merge_met
569569
assert_vit_equals_except_data(merge_vit, read_vit)
570570
assert_frame_equal(read_vit.data, expected)
571571

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+
572632
# ================================================================================================
573633
# ================================= TEST INSERT NOT MATCHED ======================================
574634
# ================================================================================================
@@ -991,6 +1051,63 @@ def test_update_and_insert_with_slicing(self, lmdb_library_factory, monkeypatch,
9911051
assert len(lt.find_keys_for_symbol(KeyType.TABLE_INDEX, "sym")) == 2
9921052
assert len(lt.find_keys_for_symbol(KeyType.VERSION, "sym")) == 2
9931053

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+
9941111
def test_update_and_insert_on_index_and_column(self, lmdb_library, monkeypatch):
9951112
lib = lmdb_library
9961113
target = pd.DataFrame(

0 commit comments

Comments
 (0)