2ab93ae51d0915cf8ce7240071b4cf4039eac8c0
tdreszer
  Fri Jun 11 17:11:50 2010 +0000
Added mdbObjsPrintUpdateLines and mdbObjsSortOnVars to aid special advanced mdbPrint options
diff --git src/hg/lib/mdb.c src/hg/lib/mdb.c
index f307823..18b4c10 100644
--- src/hg/lib/mdb.c
+++ src/hg/lib/mdb.c
@@ -8,7 +8,7 @@
 #include "jksql.h"
 #include "mdb.h"
 
-static char const rcsid[] = "$Id: mdb.c,v 1.7 2010/05/11 16:03:48 tdreszer Exp $";
+static char const rcsid[] = "$Id: mdb.c,v 1.8 2010/06/11 17:11:28 tdreszer Exp $";
 
 void mdbStaticLoad(char **row, struct mdb *ret)
 /* Load a row from mdb table into ret.  The contents of ret will
@@ -1476,6 +1476,93 @@
 return count;
 }
 
+void mdbObjPrintUpdateLines(struct mdbObj **mdbObjs,char *dbToUpdate,char *tableToUpdate, char *varsToSelect,char *varsToSet)
+// prints mdbUpdate lines to allow taking vars from one db to another (sorts mdbObjs so pass pointer)
+{
+if(dbToUpdate == NULL || tableToUpdate == NULL || varsToSelect == NULL || varsToSet == NULL)
+    errAbort("mdbObjPrintUpdateLines is missing important parameter.\n");
+
+int selCount = 0;
+char **selectVars = NULL;
+if(differentWord(varsToSelect,"obj"))
+    {
+    // Sort objs to avoid duplicate mdbUpdate statements
+    mdbObjsSortOnVars(mdbObjs, varsToSelect);
+
+    // Parse list of selcting vars (could be simply expId or expId,replicate,view)
+    selCount = chopByChar(varsToSelect,',',NULL,0);
+    if(selCount <= 0)
+        errAbort("mdbObjPrintUpdateLines is missing experiment defining variables.\n");
+    selectVars = needMem(sizeof(char *) * selCount);
+    selCount = chopByChar(varsToSelect,',',selectVars,selCount);
+    }
+// Parse list of vars to update
+int updCount = chopByChar(varsToSet,',',NULL,0);
+if(updCount <= 0)
+    errAbort("mdbObjPrintUpdateLines is missing variables to set.\n");
+char **updateVars = needMem(sizeof(char *) * updCount);
+updCount = chopByChar(varsToSet,',',updateVars,updCount);
+int ix=0;
+
+struct mdbObj *mdbObj = NULL;
+struct dyString *thisSelection = newDyString(256);
+struct dyString *lastSelection = newDyString(256);
+for(mdbObj=*mdbObjs;mdbObj!=NULL;mdbObj=mdbObj->next)
+    {
+    if(mdbObj->obj == NULL || mdbObj->deleteThis)
+        continue;
+
+    // Build this selection string
+    dyStringClear(thisSelection);
+    if(sameWord(varsToSelect,"obj"))
+        {
+        dyStringPrintf(thisSelection,"obj=%s",mdbObj->obj);
+        }
+    else
+        {
+        dyStringPrintf(thisSelection,"vars=\"");
+        for(ix = 0;ix < selCount; ix++)
+            {
+            char *val = mdbObjFindValue(mdbObj,selectVars[ix]);
+            if(val != NULL) // TODO what to do for NULLS?
+                {
+                if(strchr(val, ' ') != NULL) // Has blanks
+                    dyStringPrintf(thisSelection,"%s='%s' ",selectVars[ix],val);// FIXME: Need to make single quotes work since already within double quotes!
+                else
+                    dyStringPrintf(thisSelection,"%s=%s ",selectVars[ix],val);
+                }
+            }
+        dyStringPrintf(thisSelection,"\"");
+        }
+
+    // Don't bother making another mdpUpdate line if selection is the same.
+    if(sameString(dyStringContents(lastSelection),dyStringContents(thisSelection)))
+        continue;
+    dyStringClear(lastSelection);
+    dyStringAppend(lastSelection,dyStringContents(thisSelection));
+
+    printf("mdbUpdate %s table=%s %s",dbToUpdate,tableToUpdate,dyStringContents(thisSelection));
+
+    // Now look up the value of each var to update
+    printf(" setVars=\"");
+    for(ix = 0;ix < updCount; ix++)
+        {
+        char *val = mdbObjFindValue(mdbObj,updateVars[ix]);
+        if(val != NULL) // What to do for NULLS? Ignore
+            {
+            printf("%s=",updateVars[ix]);
+            if(strchr(val, ' ') != NULL) // Has blanks
+                printf("'%s' ",val);// FIXME: Need to make single quotes work since already within double quotes!
+            else
+                printf("%s ",val);
+            }
+        }
+    printf("\" -test\n"); // Always test first
+    }
+dyStringFree(&thisSelection);
+dyStringFree(&lastSelection);
+}
+
 // ----------------- Utilities -----------------
 
 char *mdbObjFindValue(struct mdbObj *mdbObj, char *var)
@@ -1570,10 +1657,30 @@
 {
 //char *words[48];
 char *cloneLine = cloneString(vars);
+char **words = NULL;
 int count = chopByWhite(cloneLine,NULL,0);
-char **words = needMem(sizeof(char *) * count);
+if(count)
+    {
+    words = needMem(sizeof(char *) * count);
 count = chopByWhite(cloneLine,words,count);
-//int count = chopLine(cloneLine,words);
+    }
+else
+    {
+    char try = ',';
+    count = chopByChar(cloneLine,try,NULL,0);
+    if(count <= 0)
+        {
+        char try = '\t';
+        count = chopByChar(cloneLine,try,NULL,0);
+        }
+    if(count)
+        {
+        words = needMem(sizeof(char *) * count);
+        count = chopByChar(cloneLine,try,words,count);
+        }
+    }
+if(count == 0)
+    errAbort("mdbObjReorderVars cannot parse vars argument.\n");
 
 struct mdbObj *mdbObj = NULL;
 for( mdbObj=mdbObjs; mdbObj!=NULL; mdbObj=mdbObj->next )
@@ -1617,6 +1724,41 @@
     freeMem(words);
 }
 
+int mdbObjVarCmp(const void *va, const void *vb)
+/* Compare to sort on full list of vars and vals. */
+{
+const struct mdbObj *a = *((struct mdbObj **)va);
+const struct mdbObj *b = *((struct mdbObj **)vb);
+struct mdbVar* aVar = a->vars;
+struct mdbVar* bVar = b->vars;
+for(;aVar != NULL && bVar != NULL;aVar=aVar->next,bVar=bVar->next)
+    {
+    int ret = strcmp(aVar->var, bVar->var);
+    if(ret != 0)
+        return ret;
+    ret = strcmp(aVar->val, bVar->val);
+    if(ret != 0)
+        return ret;
+    }
+if(aVar != NULL)
+    return -1;
+if(bVar != NULL)
+    return 1;
+return 0;
+}
+
+
+
+void mdbObjsSortOnVars(struct mdbObj **mdbObjs, char *vars)
+// Sorts on var,val pairs vars lists: fwd case-sensitive.  Assumes all objs' vars are in identical order.
+// Optionally give list of vars "cell antibody treatment" to sort on (bringing to front of vars lists).
+{  // NOTE: assumes all var pairs match (e.g. every obj has cell,treatment,antibody,... and missing treatment messes up sort)
+if(vars != NULL)
+    mdbObjReorderVars(*mdbObjs,vars,FALSE);
+
+slSort(mdbObjs, mdbObjVarCmp);
+}
+
 void mdbObjRemoveVars(struct mdbObj *mdbObjs, char *vars)
 // Prunes list of vars for an object, freeing the memory.  Doesn't touch DB.
 {