From 1d3d08fe292d7ed294dd42f80d5aa45cfbe3b1ab Mon Sep 17 00:00:00 2001
From: Renaud Le Gac <legac@cppm.in2p3.fr>
Date: Thu, 21 Mar 2013 11:23:43 +0100
Subject: [PATCH] More syntax for foreign field.

---
 models/db_tools.py            | 13 +++++-----
 modules/plugin_dbui/helper.py | 46 ++++++++++++++++++++++++++++++-----
 static/plugin_dbui/CHANGELOG  |  1 +
 3 files changed, 48 insertions(+), 12 deletions(-)

diff --git a/models/db_tools.py b/models/db_tools.py
index 45068b70..4eefa99a 100644
--- a/models/db_tools.py
+++ b/models/db_tools.py
@@ -23,26 +23,27 @@ tp_ratio = \
 "Parameter for fuzzy string search."
 
 db.define_table("harvesters",
-    Field("id_teams", db.teams, default=undef_id, label='Team'),
-    Field("id_projects", db.projects, default=undef_id, label='Project'),
+    Field("id_teams", "reference teams", default=undef_id, label='Team'),
+    Field("id_projects", "reference projects", default=undef_id, label='Project'),
     Field("controller", "string", notnull=True, comment=tp_controller),
     Field("host", "string", notnull=True, default='cdsweb.cern.ch', label='Store', comment=tp_host),
     Field("collections", "string", comment=tp_collections),
     Field("ratio", "double", notnull=True, default=1.0, comment=tp_ratio),
-    Field("id_categories", db.categories, default=1, label='Category', comment=tp_category),
+    Field("id_categories", "reference categories", default=1, label='Category', comment=tp_category),
     migrate="harvesters.table")
 
 db.harvesters.controller.requires = \
 IS_IN_SET(['articles', 'notes', 'preprints', 'proceedings', 'reports', 'talks', 'theses'])
 
+# TEST THE DIFFERENT SYNTAX DEFINING FOREIGN KEY
 db.harvesters.id_categories.requires = \
 IS_IN_DB(db, 'categories.id', 'categories.code')
 
 db.harvesters.id_projects.requires = \
-IS_IN_DB(db, 'projects.id', 'projects.project')
+IS_IN_DB(db, 'projects.project')
 
-db.harvesters.id_teams.requires = \
-IS_IN_DB(db, 'teams.id', 'teams.team')
+#db.harvesters.id_teams.requires = \
+#IS_IN_DB(db, 'teams.id', 'teams.team')
 
 db.harvesters.ratio.requires = \
 IS_FLOAT_IN_RANGE(0., 1.0)
\ No newline at end of file
diff --git a/modules/plugin_dbui/helper.py b/modules/plugin_dbui/helper.py
index 27ba60f5..2a78e532 100644
--- a/modules/plugin_dbui/helper.py
+++ b/modules/plugin_dbui/helper.py
@@ -202,20 +202,54 @@ def get_file_paths(path, ext=None, alpha=True):
 
 
 def get_foreign_field(field):
-    """Helper function returning a tuple containing the parent tablename,
-    the parent fieldname and the primary key name of the parent table. 
-    
-        table.field --> k_table.k_field
-        table.field == k_table.k_key
+    """Helper function returning a tuple (k_tablename, k_fieldname, k_keyname)
+    where:
+        
+        k_tablename is the name of the parent table
+        
+        k_fieldname is the name of the parent field
+            table.field --> k_table.k_field
         
+        k_keyname is the name of the primary key of the parent table
+        requires by the left join. In most of the case it is id
+            table.field == k_table.k_key
+     
     Otherwise return None.
     
     """
+    if not is_foreign_field(field):
+        return None
+    
+    # foreign field validators IS_IN_BD contains all information 
+    # on the parent key for the left join and on the parent field
     validators = as_list(field.requires)
 
+    # Several syntax are allowed
+
+    # IS_IN_DB is use.
     for vdt in validators:
+        
         if isinstance(vdt, IS_IN_DB):
-            return (vdt.ktable, vdt.ks[0], vdt.ks[1])   
+            # IS_IN_DB contains only the parent field. 
+            # The key for the left join is the id key of the parent table
+            if len(vdt.ks) == 1:
+                return (vdt.ktable, vdt.ks[0], 'id')
+            
+            # IS_IN_DB contains the key for the join and the parent field 
+            else:
+                return (vdt.ktable, vdt.ks[0], vdt.ks[1])   
+    
+    # IS_IN_DB is not use. 
+    # The parent key for the left join is the id key of the parent table
+    # the parent field is the first field of the parent table which differs id
+    if not validators:
+        i = field.type.index(' ')
+        ktablename = field.type[i:].strip()
+        
+        for kfield in field._db[ktablename]:
+            if kfield.name != 'id':
+                return (ktablename, kfield.name, 'id')
+            
 
     return None
 
diff --git a/static/plugin_dbui/CHANGELOG b/static/plugin_dbui/CHANGELOG
index 0beb3aad..fc4c46f2 100644
--- a/static/plugin_dbui/CHANGELOG
+++ b/static/plugin_dbui/CHANGELOG
@@ -2,6 +2,7 @@
 
 HEAD
   - Upgrade to run with alias table.
+  - More syntax to define foreign key.
 
 0.4.10.3 (Mar 2013)
   - Fix a bug in App.BasePanelWithSelector for IE.
-- 
GitLab