5
5
Dict ,
6
6
Generic ,
7
7
List ,
8
+ Literal ,
8
9
Mapping ,
9
10
MutableMapping ,
10
11
Optional ,
14
15
TypeVar ,
15
16
Union ,
16
17
cast ,
18
+ overload ,
17
19
)
18
20
19
21
from aibs_informatics_core .env import EnvBase
42
44
from botocore .exceptions import ClientError
43
45
44
46
from aibs_informatics_aws_utils .core import get_client_error_code
47
+ from aibs_informatics_aws_utils .dynamodb .conditions import condition_to_str
45
48
from aibs_informatics_aws_utils .dynamodb .functions import (
46
49
convert_floats_to_decimals ,
47
50
execute_partiql_statement ,
@@ -72,8 +75,7 @@ def check_db_query_unique(
72
75
key_condition_expression : Optional [ConditionBase ] = None ,
73
76
filter_expression : Optional [ConditionBase ] = None ,
74
77
):
75
- # TODO: this should be len(query_result) > 1
76
- if len (query_result ) != 1 :
78
+ if len (query_result ) > 1 :
77
79
readable_key_expression : Optional [BuiltConditionExpression ] = None
78
80
if key_condition_expression :
79
81
expression_builder = ConditionExpressionBuilder ()
@@ -245,8 +247,6 @@ def build_optimized_condition_expression_set(
245
247
246
248
@dataclass
247
249
class DynamoDBTable (LoggingMixin , Generic [DB_MODEL , DB_INDEX ]):
248
- # env_base: EnvBase = field(default_factory=EnvBase.from_env)
249
-
250
250
def __post_init__ (self ):
251
251
check_table_name_and_index_match (self .table_name , self .get_db_index_cls ())
252
252
@@ -432,10 +432,9 @@ def query(
432
432
expect_non_empty (bool, optional): Whether the resulting query should return at least
433
433
one result. An error will be raised if expect_non_empty=True and 0 results were
434
434
returned by the query.
435
- expect_unique (bool, option): Whether the result of the query is expected to be
436
- unique (i.e. returns 1 and ONLY 1 result). An error will be raised if 0 or
437
- more than 1 results were returned for the query.
438
-
435
+ expect_unique (bool, option): Whether the result of the query is expected to
436
+ return AT MOST one result. An error will be raised if expect_unique=True and MORE
437
+ than 1 result was returned for the query.
439
438
Returns:
440
439
Sequence[Dict[str, Any]]: A sequence of dictionaries representing database rows
441
440
where partition_key/sort_key and filter conditions are satisfied.
@@ -455,7 +454,8 @@ def query(
455
454
456
455
self .log .info (
457
456
f"Calling query on { self .table_name } table (index: { index_name } , "
458
- f"key condition: { key_condition_expression } , filters: { filter_expression } )"
457
+ f"key condition: { condition_to_str (key_condition_expression )} , "
458
+ f"filters: { condition_to_str (filter_expression )} )"
459
459
)
460
460
461
461
items = table_query (
@@ -507,9 +507,9 @@ def scan(
507
507
expect_non_empty (bool, optional): Whether the resulting query should return at least
508
508
one result. An error will be raised if expect_non_empty=True and 0 results were
509
509
returned by the query.
510
- expect_unique (bool, option): Whether the result of the query is expected to be
511
- unique (i.e. returns 1 and ONLY 1 result) . An error will be raised if 0 or
512
- more than 1 results were returned for the query.
510
+ expect_unique (bool, option): Whether the result of the query is expected to
511
+ return AT MOST one result. An error will be raised if expect_unique=True and MORE
512
+ than 1 result was returned for the query.
513
513
514
514
Returns:
515
515
Sequence[Dict[str, Any]]: A sequence of dictionaries representing database rows
@@ -524,7 +524,7 @@ def scan(
524
524
525
525
self .log .info (
526
526
f"Calling scan on { self .table_name } table (index: { index_name } ,"
527
- f" filters: { filter_expression } )"
527
+ f" filters: { condition_to_str ( filter_expression ) } )"
528
528
)
529
529
530
530
items = table_scan (
@@ -611,17 +611,9 @@ def put(
611
611
condition_expression : Optional [ConditionBase ] = None ,
612
612
** table_put_item_kwargs ,
613
613
) -> DB_MODEL :
614
- # Convert our ConditionBase class to a readable string (for logging/debugging purposes)
615
- if condition_expression :
616
- expression = ConditionExpressionBuilder ().build_expression (condition_expression )
617
- expression_str = (
618
- f"({ expression .condition_expression } , "
619
- f"{ expression .attribute_name_placeholders } , "
620
- f"{ expression .attribute_value_placeholders } )"
621
- )
622
- else :
623
- expression_str = "None"
624
- put_summary = f"(entry: { entry } , condition_expression: { expression_str } )"
614
+ put_summary = (
615
+ f"(entry: { entry } , condition_expression: { condition_to_str (condition_expression )} )"
616
+ )
625
617
self .log .debug (f"{ self .table_name } - Putting new entry: { put_summary } " )
626
618
627
619
e_msg_intro = f"{ self .table_name } - Error putting entry: { put_summary } ."
@@ -659,22 +651,30 @@ def update(
659
651
660
652
for k in key :
661
653
new_attributes .pop (k , None )
654
+ # Add k:v pair from new_attributes if new != old value for a given key
655
+ new_clean_attrs : Dict [str , Any ] = {}
656
+ if old_entry :
657
+ for k , new_v in new_attributes .items ():
658
+ if getattr (old_entry , k ) != new_v :
659
+ new_clean_attrs [k ] = new_v
660
+ else :
661
+ new_clean_attrs = new_attributes
662
662
663
- if not new_attributes :
663
+ if not new_clean_attrs :
664
664
self .log .debug (
665
665
f"{ self .table_name } - No attr_updates to do! Skipping _update_entry call."
666
666
)
667
667
if not old_entry :
668
668
old_entry = self .get (key )
669
669
return old_entry
670
670
671
- update_summary = f"(old_entry: { old_entry } , new_attributes: { new_attributes } )"
671
+ update_summary = f"(old_entry: { old_entry } , new_attributes: { new_clean_attrs } )"
672
672
self .log .debug (f"{ self .table_name } - Updating entry: { update_summary } " )
673
673
try :
674
674
updated_item = table_update_item (
675
675
table_name = self .table_name ,
676
676
key = key ,
677
- attributes = new_attributes ,
677
+ attributes = new_clean_attrs ,
678
678
return_values = "ALL_NEW" ,
679
679
** table_update_item_kwargs ,
680
680
)
@@ -694,6 +694,29 @@ def update(
694
694
self .log .debug (f"{ self .table_name } - Successfully updated entry: { updated_entry } " )
695
695
return updated_entry
696
696
697
+ @overload
698
+ def delete (
699
+ self ,
700
+ key : Union [DynamoDBKey , DB_MODEL ],
701
+ error_on_nonexistent : Literal [True ],
702
+ ) -> DB_MODEL :
703
+ ...
704
+
705
+ @overload
706
+ def delete (
707
+ self ,
708
+ key : Union [DynamoDBKey , DB_MODEL ],
709
+ error_on_nonexistent : Literal [False ],
710
+ ) -> Optional [DB_MODEL ]:
711
+ ...
712
+
713
+ @overload
714
+ def delete (
715
+ self ,
716
+ key : Union [DynamoDBKey , DB_MODEL ],
717
+ ) -> Optional [DB_MODEL ]:
718
+ ...
719
+
697
720
def delete (
698
721
self ,
699
722
key : Union [DynamoDBKey , DB_MODEL ],
0 commit comments