From 4229fe8b18f32139287ba69c10ae0f0a58db2e32 Mon Sep 17 00:00:00 2001 From: Conatum Date: Sun, 19 Sep 2021 09:54:08 +0300 Subject: [PATCH] (Data): Small extensions to core data interfaces. Add `LEQ` condition type. Ensure that batch updates don't fire with nothing to update. Add `cast_row` to `update_many` for handling typed `NULL`s. --- bot/data/conditions.py | 15 +++++++++++++++ bot/data/interfaces.py | 3 ++- bot/data/queries.py | 5 +++-- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/bot/data/conditions.py b/bot/data/conditions.py index ca01ea5d..4687a929 100644 --- a/bot/data/conditions.py +++ b/bot/data/conditions.py @@ -45,6 +45,21 @@ class GEQ(Condition): values.append(item) +class LEQ(Condition): + __slots__ = ('value',) + + def __init__(self, value): + self.value = value + + def apply(self, key, values, conditions): + item = self.value + if isinstance(item, (list, tuple)): + raise ValueError("Cannot apply LEQ condition to a list!") + else: + conditions.append("{} <= {}".format(key, _replace_char)) + values.append(item) + + class Constant(Condition): __slots__ = ('value',) diff --git a/bot/data/interfaces.py b/bot/data/interfaces.py index 88e60a15..266b5a03 100644 --- a/bot/data/interfaces.py +++ b/bot/data/interfaces.py @@ -113,7 +113,8 @@ class Row: try: yield self._pending finally: - self.update(**self._pending) + if self._pending: + self.update(**self._pending) self._pending = None def _refresh(self): diff --git a/bot/data/queries.py b/bot/data/queries.py index e4cce52d..6e661e99 100644 --- a/bot/data/queries.py +++ b/bot/data/queries.py @@ -126,7 +126,7 @@ def upsert(table, constraint, cursor=None, **values): return cursor.fetchone() -def update_many(table, *values, set_keys=None, where_keys=None, cursor=None): +def update_many(table, *values, set_keys=None, where_keys=None, cast_row=None, cursor=None): cursor = cursor or conn.cursor() return execute_values( @@ -134,13 +134,14 @@ def update_many(table, *values, set_keys=None, where_keys=None, cursor=None): """ UPDATE {table} SET {set_clause} - FROM (VALUES %s) + FROM (VALUES {cast_row}%s) AS {temp_table} WHERE {where_clause} RETURNING * """.format( table=table, set_clause=', '.join("{0} = _t.{0}".format(key) for key in set_keys), + cast_row=cast_row + ',' if cast_row else '', where_clause=' AND '.join("{1}.{0} = _t.{0}".format(key, table) for key in where_keys), temp_table="_t ({})".format(', '.join(set_keys + where_keys)) ),