From 14fb825c963ee363756451ae39a4acfa619e3c24 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Sat, 17 Dec 2022 13:00:23 +0100
Subject: [PATCH 1/5] sql: factorize getting single field value from row
 (#72312)

---
 wcs/sql.py | 112 ++++++++++++++++++++++++++++-------------------------
 1 file changed, 59 insertions(+), 53 deletions(-)

diff --git a/wcs/sql.py b/wcs/sql.py
index d7d6a1f26..1f3f364ca 100644
--- a/wcs/sql.py
+++ b/wcs/sql.py
@@ -2475,6 +2475,63 @@ class SqlMixin:
                 )
         return sql_dict
 
+    @classmethod
+    def _col2obdata(cls, row, i, field):
+        obdata = {}
+        sql_type = SQL_TYPE_MAPPING.get(field.key, 'varchar')
+        if sql_type is None:
+            return ({}, i)
+        value = row[i]
+        if value is not None:
+            value = str_encode(value)
+            if field.key == 'ranked-items':
+                d = {}
+                for data, rank in value:
+                    try:
+                        d[data] = int(rank)
+                    except ValueError:
+                        d[data] = rank
+                value = d
+            elif field.key == 'password':
+                d = {}
+                for fmt, val in value:
+                    d[fmt] = force_str(val)
+                value = d
+            elif field.key == 'computed':
+                if isinstance(value, dict) and value.get('@type') == 'computed-data':
+                    value = value.get('data')
+            if sql_type == 'date':
+                value = value.timetuple()
+            elif sql_type == 'bytea':
+                value = pickle_loads(value)
+            elif sql_type == 'jsonb' and isinstance(value, dict) and value.get('schema'):
+                # block field, adapt date/field values
+                for field_id, field_type in value.get('schema').items():
+                    if field_type not in ('date', 'file'):
+                        continue
+                    for entry in value.get('data') or []:
+                        subvalue = entry.get(field_id)
+                        if subvalue and field_type == 'date':
+                            entry[field_id] = time.strptime(subvalue, '%Y-%m-%d')
+                        elif subvalue and field_type == 'file':
+                            entry[field_id] = PicklableUpload.__new__(PicklableUpload)
+                            entry[field_id].__setstate__(subvalue)
+
+        obdata[field.id] = value
+        i += 1
+        if field.store_display_value:
+            value = str_encode(row[i])
+            obdata['%s_display' % field.id] = value
+            i += 1
+        if field.store_structured_value:
+            value = row[i]
+            if value is not None:
+                obdata['%s_structured' % field.id] = pickle_loads(value)
+                if obdata['%s_structured' % field.id] is None:
+                    del obdata['%s_structured' % field.id]
+            i += 1
+        return (obdata, i)
+
     @classmethod
     def _row2obdata(cls, row, formdef):
         obdata = {}
@@ -2482,59 +2539,8 @@ class SqlMixin:
         if formdef.geolocations:
             i += len(formdef.geolocations.keys())
         for field in formdef.get_all_fields():
-            sql_type = SQL_TYPE_MAPPING.get(field.key, 'varchar')
-            if sql_type is None:
-                continue
-            value = row[i]
-            if value is not None:
-                value = str_encode(value)
-                if field.key == 'ranked-items':
-                    d = {}
-                    for data, rank in value:
-                        try:
-                            d[data] = int(rank)
-                        except ValueError:
-                            d[data] = rank
-                    value = d
-                elif field.key == 'password':
-                    d = {}
-                    for fmt, val in value:
-                        d[fmt] = force_str(val)
-                    value = d
-                elif field.key == 'computed':
-                    if isinstance(value, dict) and value.get('@type') == 'computed-data':
-                        value = value.get('data')
-                if sql_type == 'date':
-                    value = value.timetuple()
-                elif sql_type == 'bytea':
-                    value = pickle_loads(value)
-                elif sql_type == 'jsonb' and isinstance(value, dict) and value.get('schema'):
-                    # block field, adapt date/field values
-                    for field_id, field_type in value.get('schema').items():
-                        if field_type not in ('date', 'file'):
-                            continue
-                        for entry in value.get('data') or []:
-                            subvalue = entry.get(field_id)
-                            if subvalue and field_type == 'date':
-                                entry[field_id] = time.strptime(subvalue, '%Y-%m-%d')
-                            elif subvalue and field_type == 'file':
-                                entry[field_id] = PicklableUpload.__new__(PicklableUpload)
-                                entry[field_id].__setstate__(subvalue)
-
-            obdata[field.id] = value
-            i += 1
-            if field.store_display_value:
-                value = str_encode(row[i])
-                obdata['%s_display' % field.id] = value
-                i += 1
-            if field.store_structured_value:
-                value = row[i]
-                if value is not None:
-                    obdata['%s_structured' % field.id] = pickle_loads(value)
-                    if obdata['%s_structured' % field.id] is None:
-                        del obdata['%s_structured' % field.id]
-                i += 1
-
+            coldata, i = cls._col2obdata(row, i, field)
+            obdata.update(coldata)
         return obdata
 
     @classmethod
-- 
2.39.0

