src/hg/lib/metaTbl.c 1.9
1.9 2010/04/01 23:49:49 tdreszer
Reorganized and filled out metadataForTable routine
Index: src/hg/lib/metaTbl.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/lib/metaTbl.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -b -B -U 1000000 -r1.8 -r1.9
--- src/hg/lib/metaTbl.c 31 Mar 2010 23:34:18 -0000 1.8
+++ src/hg/lib/metaTbl.c 1 Apr 2010 23:49:49 -0000 1.9
@@ -1,1665 +1,1777 @@
/* metaTbl.c was originally generated by the autoSql program, which also
* generated metaTbl.h and metaTbl.sql. This module links the database and
* the RAM representation of objects. */
#include "common.h"
#include "linefile.h"
#include "dystring.h"
#include "jksql.h"
#include "metaTbl.h"
static char const rcsid[] = "$Id$";
void metaTblStaticLoad(char **row, struct metaTbl *ret)
/* Load a row from metaTbl table into ret. The contents of ret will
* be replaced at the next call to this function. */
{
ret->objName = row[0];
ret->objType = row[1];
ret->var = row[2];
ret->varType = row[3];
ret->val = row[4];
}
struct metaTbl *metaTblLoadByQuery(struct sqlConnection *conn, char *query)
/* Load all metaTbl from table that satisfy the query given.
* Where query is of the form 'select * from example where something=something'
* or 'select example.* from example, anotherTable where example.something =
* anotherTable.something'.
* Dispose of this with metaTblFreeList(). */
{
struct metaTbl *list = NULL, *el;
struct sqlResult *sr;
char **row;
sr = sqlGetResult(conn, query);
while ((row = sqlNextRow(sr)) != NULL)
{
el = metaTblLoad(row);
slAddHead(&list, el);
}
slReverse(&list);
sqlFreeResult(&sr);
return list;
}
void metaTblSaveToDb(struct sqlConnection *conn, struct metaTbl *el, char *tableName, int updateSize)
/* Save metaTbl as a row to the table specified by tableName.
* As blob fields may be arbitrary size updateSize specifies the approx size
* of a string that would contain the entire query. Arrays of native types are
* converted to comma separated strings and loaded as such, User defined types are
* inserted as NULL. Note that strings must be escaped to allow insertion into the database.
* For example "autosql's features include" --> "autosql\'s features include"
* If worried about this use metaTblSaveToDbEscaped() */
{
struct dyString *update = newDyString(updateSize);
dyStringPrintf(update, "insert into %s values ( '%s','%s','%s','%s',%s)",
tableName, el->objName, el->objType, el->var, el->varType, el->val);
sqlUpdate(conn, update->string);
freeDyString(&update);
}
void metaTblSaveToDbEscaped(struct sqlConnection *conn, struct metaTbl *el, char *tableName, int updateSize)
/* Save metaTbl as a row to the table specified by tableName.
* As blob fields may be arbitrary size updateSize specifies the approx size.
* of a string that would contain the entire query. Automatically
* escapes all simple strings (not arrays of string) but may be slower than metaTblSaveToDb().
* For example automatically copies and converts:
* "autosql's features include" --> "autosql\'s features include"
* before inserting into database. */
{
struct dyString *update = newDyString(updateSize);
char *objName, *objType, *var, *varType, *val;
objName = sqlEscapeString(el->objName);
objType = sqlEscapeString(el->objType);
var = sqlEscapeString(el->var);
varType = sqlEscapeString(el->varType);
val = sqlEscapeString(el->val);
dyStringPrintf(update, "insert into %s values ( '%s','%s','%s','%s','%s')",
tableName, objName, objType, var, varType, val);
sqlUpdate(conn, update->string);
freeDyString(&update);
freez(&objName);
freez(&objType);
freez(&var);
freez(&varType);
freez(&val);
}
struct metaTbl *metaTblLoad(char **row)
/* Load a metaTbl from row fetched with select * from metaTbl
* from database. Dispose of this with metaTblFree(). */
{
struct metaTbl *ret;
AllocVar(ret);
ret->objName = cloneString(row[0]);
ret->objType = cloneString(row[1]);
ret->var = cloneString(row[2]);
ret->varType = cloneString(row[3]);
ret->val = cloneString(row[4]);
return ret;
}
struct metaTbl *metaTblLoadAll(char *fileName)
/* Load all metaTbl from a whitespace-separated file.
* Dispose of this with metaTblFreeList(). */
{
struct metaTbl *list = NULL, *el;
struct lineFile *lf = lineFileOpen(fileName, TRUE);
char *row[5];
while (lineFileRow(lf, row))
{
el = metaTblLoad(row);
slAddHead(&list, el);
}
lineFileClose(&lf);
slReverse(&list);
return list;
}
struct metaTbl *metaTblLoadAllByChar(char *fileName, char chopper)
/* Load all metaTbl from a chopper separated file.
* Dispose of this with metaTblFreeList(). */
{
struct metaTbl *list = NULL, *el;
struct lineFile *lf = lineFileOpen(fileName, TRUE);
char *row[5];
while (lineFileNextCharRow(lf, chopper, row, ArraySize(row)))
{
el = metaTblLoad(row);
slAddHead(&list, el);
}
lineFileClose(&lf);
slReverse(&list);
return list;
}
struct metaTbl *metaTblCommaIn(char **pS, struct metaTbl *ret)
/* Create a metaTbl out of a comma separated string.
* This will fill in ret if non-null, otherwise will
* return a new metaTbl */
{
char *s = *pS;
if (ret == NULL)
AllocVar(ret);
ret->objName = sqlStringComma(&s);
ret->objType = sqlStringComma(&s);
ret->var = sqlStringComma(&s);
ret->varType = sqlStringComma(&s);
ret->val = sqlStringComma(&s);
*pS = s;
return ret;
}
void metaTblFree(struct metaTbl **pEl)
/* Free a single dynamically allocated metaTbl such as created
* with metaTblLoad(). */
{
struct metaTbl *el;
if ((el = *pEl) == NULL) return;
freeMem(el->objName);
freeMem(el->objType);
freeMem(el->var);
freeMem(el->varType);
freeMem(el->val);
freez(pEl);
}
void metaTblFreeList(struct metaTbl **pList)
/* Free a list of dynamically allocated metaTbl's */
{
struct metaTbl *el, *next;
for (el = *pList; el != NULL; el = next)
{
next = el->next;
metaTblFree(&el);
}
*pList = NULL;
}
void metaTblOutput(struct metaTbl *el, FILE *f, char sep, char lastSep)
/* Print out metaTbl. Separate fields with sep. Follow last field with lastSep. */
{
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->objName);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->objType);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->var);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->varType);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->val);
if (sep == ',') fputc('"',f);
fputc(lastSep,f);
}
/* -------------------------------- End autoSql Generated Code -------------------------------- */
#include "ra.h"
#include "hgConfig.h"
#include "obscure.h"
// ------- (static) convert from autoSql -------
static void metaVarFree(struct metaVar **metaVarPtr)
// Frees a single metaVar struct
{
freeMem((*metaVarPtr)->val);
freeMem((*metaVarPtr)->var);
freez(metaVarPtr);
}
static void metaLeafObjFree(struct metaLeafObj **leafObjPtr)
// Frees a single metaVar struct
{
freeMem((*leafObjPtr)->obj);
freez(leafObjPtr);
}
static void metaLimbValFree(struct metaLimbVal **limbValPtr)
// Frees a single metaVar struct
{
struct metaLimbVal *limbVal = *limbValPtr;
// Free hash first (shared memory)
hashFree(&(limbVal->objHash));
struct metaLeafObj *leafObj = NULL;
while((leafObj = slPopHead(&(limbVal->objs))) != NULL)
metaLeafObjFree(&leafObj);
freeMem(limbVal->val);
freez(limbValPtr);
}
static struct metaObj *metaObjsLoadFromMemory(struct metaTbl **metaTblPtr,boolean buildHashes)
// Load all metaObjs from in memory metaTbl struct, cannibalize strings. Expects sorted order.
{
struct metaObj *metaObj = NULL;
struct metaObj *metaObjs = NULL;
struct metaVar *metaVar;
struct metaTbl *thisRow;
while((thisRow = slPopHead(metaTblPtr)) != NULL)
{
if (metaObj == NULL || differentString(thisRow->objName,metaObj->obj) )
{
// Finish last object before starting next!
if(metaObj!= NULL)
slReverse(&(metaObjs->vars));
// Start new object
AllocVar(metaObj);
metaObj->obj = thisRow->objName;
metaObj->objType = metaObjTypeStringToEnum(thisRow->objType);
freeMem(thisRow->objType);
if ( buildHashes )
metaObj->varHash = hashNew(0);
slAddHead(&metaObjs,metaObj);
}
else
{
freeMem(thisRow->objName); // Already got this from prev row
freeMem(thisRow->objType);
}
AllocVar(metaVar);
metaVar->var = thisRow->var;
metaVar->varType = metaVarTypeStringToEnum(thisRow->varType);
metaVar->val = thisRow->val;
slAddHead(&(metaObj->vars),metaVar);
if ( buildHashes )
hashAddUnique(metaObj->varHash, metaVar->var, metaVar); // pointer to struct to resolve type
freeMem(thisRow);
}
// Finish very last object
if(metaObjs && metaObjs->vars)
slReverse(&(metaObjs->vars));
if(metaObjs)
slReverse(&metaObjs);
return metaObjs;
}
static struct metaByVar *metaByVarsLoadFromMemory(struct metaTbl **metaTblPtr,boolean buildHashes)
// Load all metaVars from in memorys metaTbl struct, cannibalize strings. Expects sorted order.
{
struct metaByVar *rootVars = NULL;
struct metaByVar *rootVar = NULL;
struct metaLimbVal *limbVal = NULL;
struct metaLeafObj *leafObj;
struct metaTbl *thisRow;
while((thisRow = slPopHead(metaTblPtr)) != NULL)
{
// Start at root
if (rootVar == NULL || differentString(thisRow->var,rootVar->var) )
{
// Finish last var before starting next!
if(rootVars && rootVars->vals && rootVars->vals->objs)
slReverse(&(rootVars->vals->objs));
if(rootVars && rootVars->vals)
slReverse(&(rootVars->vals));
// Start new var
AllocVar(rootVar);
limbVal = NULL; // Very important!
rootVar->var = thisRow->var;
rootVar->varType = metaVarTypeStringToEnum(thisRow->varType);
freeMem(thisRow->varType);
if ( buildHashes )
rootVar->valHash = hashNew(0);
slAddHead(&rootVars,rootVar);
}
else
{
freeMem(thisRow->var); // Already got this from prev row
freeMem(thisRow->varType);
}
// Continue with limb
if (limbVal == NULL || differentString(thisRow->val,limbVal->val) )
{
// Finish last val before starting next!
if(limbVal != NULL && limbVal->objs != NULL)
slReverse(&(limbVal->objs));
// Start new val
AllocVar(limbVal);
limbVal->val = thisRow->val; // FIXME: binary?
if ( buildHashes )
{
hashAddUnique(rootVar->valHash, limbVal->val, limbVal); // Pointer to struct to get to objHash
limbVal->objHash = hashNew(0);
}
slAddHead(&(rootVar->vals),limbVal);
}
else
freeMem(thisRow->val); // Already got this from prev row
// End with leaf
AllocVar(leafObj);
leafObj->obj = thisRow->objName;
leafObj->objType = metaObjTypeStringToEnum(thisRow->objType);
freeMem(thisRow->objType);
if ( buildHashes )
hashAddUnique(limbVal->objHash, leafObj->obj, leafObj); // Pointer to struct to resolve type!
slAddHead(&(limbVal->objs),leafObj);
freeMem(thisRow);
}
// Finish very last object
if(rootVars && rootVars->vals && rootVars->vals->objs)
slReverse(&(rootVars->vals->objs));
if(rootVars && rootVars->vals)
slReverse(&(rootVars->vals));
if(rootVars && rootVars->vals)
slReverse(&rootVars);
return rootVars;
}
+static int metaObjCRC(struct metaObj *metaObjs)
+// returns a summ of all individual CRC values of all metObj strings
+{
+int crc = 0;
+struct metaObj *metaObj = NULL;
+for(metaObj=metaObjs;metaObj!=NULL;metaObj=metaObj->next)
+ {
+ if(metaObj->obj != NULL)
+ crc += hashCrc(metaObj->obj);
+
+ struct metaVar *metaVar = NULL;
+ for(metaVar=metaObj->vars;metaVar!=NULL;metaVar=metaVar->next)
+ {
+ if(metaVar->var != NULL)
+ crc += hashCrc(metaVar->var);
+ if(metaVar->varType == vtTxt && metaVar->val != NULL)
+ crc += hashCrc(metaVar->val);
+ }
+ }
+
+return crc;
+}
+
// -------------- Sort primitives --------------
int metaObjCmp(const void *va, const void *vb)
/* Compare to sort on label. */
{
const struct metaObj *a = *((struct metaObj **)va);
const struct metaObj *b = *((struct metaObj **)vb);
return strcasecmp(a->obj, b->obj);
}
int metaVarCmp(const void *va, const void *vb)
/* Compare to sort on label. */
{
const struct metaVar *a = *((struct metaVar **)va);
const struct metaVar *b = *((struct metaVar **)vb);
return strcasecmp(a->var, b->var);
}
// -------------- Enum to Strings --------------
enum metaObjType metaObjTypeStringToEnum(char *objType)
// Convert metadata objType string to enum
{
if(sameWord(objType,"table"))
return otTable;
if(sameWord(objType,"file"))
return otFile;
return otUnknown;
}
char *metaObjTypeEnumToString(enum metaObjType objType)
// Convert metadata objType enum string
{
switch (objType)
{
case otTable: return "table";
case otFile: return "file";
default: return "unknown";
}
}
enum metaVarType metaVarTypeStringToEnum(char *varType)
// Convert metadata varType string to enum
{
if(sameWord(varType,"txt"))
return vtTxt;
if(sameWord(varType,"binary"))
return vtBinary;
return vtUnknown;
}
char *metaVarTypeEnumToString(enum metaVarType varType)
// Convert metadata varType enum string
{
switch (varType)
{
case vtTxt: return "txt";
case vtBinary: return "binary";
default: return "unknown";
}
}
// ------ Parsing lines ------
struct metaObj *metadataLineParse(char *line)
/* Parses a single formatted metadata line into metaObj for updates or queries. */
{
int thisWord = 0;
struct metaObj *metaObj;
struct metaVar *metaVar;
char *cloneLine = cloneString(line);
// initial chop and determine if this looks like metadata
int count = chopByWhiteRespectDoubleQuotes(cloneLine,NULL,0);
char **words = needMem(sizeof(char *) * count);
count = chopByWhiteRespectDoubleQuotes(cloneLine,words,count);
if(count < 3 || words[thisWord] == NULL || differentWord(words[thisWord],"metadata"))
{
errAbort("This is not formatted metadata:\n\t%s\n",line);
}
verbose(3, "metadataLineParse() word count:%d\n\t%s\n",count,line);
// Get objName and figure out if this is a delete line
AllocVar(metaObj);
thisWord++;
if(strchr(words[thisWord], '=') == NULL)
{
metaObj->obj = cloneString(words[thisWord++]);
verbose(3, "metadataLineParse() obj=%s\n",metaObj->obj);
if(sameWord(words[thisWord],"delete"))
{
metaObj->deleteThis = TRUE;
thisWord++;
}
if(thisWord < count && strchr(words[thisWord], '=') == NULL)
{
metaObj->objType = metaObjTypeStringToEnum(words[thisWord]);
if(metaObj->objType == otUnknown)
{
errAbort("Unknown objType '%s'. This is not properly formatted metadata:\n\t%s\n",words[thisWord],line);
//metaObjsFree(&metaObj);
//return NULL;
}
thisWord++;
}
if(thisWord < count && sameWord(words[thisWord],"delete")) // Could be obj delete... or obj objType delete
{
metaObj->deleteThis = TRUE;
thisWord++;
}
}
// From now on all words are expected to be var=val pairs!
metaObj->varHash = hashNew(0);
for(;thisWord<count;thisWord++)
{
if(strchr(words[thisWord], '=') == NULL)
{
errAbort("Expected 'var=val' but found '%s'. This is not properly formatted metadata:\n\t%s\n",words[thisWord],line);
//metaObjsFree(&metaObj);
//return NULL;
}
AllocVar(metaVar);
metaVar->var = cloneNextWordByDelimiter(&(words[thisWord]),'=');
metaVar->varType = vtTxt; // FIXME: binary?
metaVar->val = cloneString(words[thisWord]);
verbose(3, "metadataLineParse() var=val: %s=%s\n",metaVar->var,metaVar->val);
struct metaVar *oldVar = (struct metaVar *)hashFindVal(metaObj->varHash, metaVar->var);
if(oldVar)
{
verbose(1, "The same variable appears twice: %s=%s and %s=%s. Ignoring second value.\n",
oldVar->var,oldVar->val,metaVar->var,metaVar->val);
metaVarFree(&metaVar);
}
else
{
hashAdd(metaObj->varHash, metaVar->var, metaVar); // pointer to struct to resolve type
slAddHead(&(metaObj->vars),metaVar);
}
}
freeMem(words);
// Special for old style ENCODE metadata
if(metaObj->obj == NULL)
{
char * tableName = NULL;
char * fileName = NULL;
for(metaVar = metaObj->vars;
metaVar != NULL && (tableName == NULL || fileName == NULL);
metaVar = metaVar->next)
{
if(sameString(metaVar->var,"tableName"))
tableName = metaVar->val;
else if(sameString(metaVar->var,"fileName"))
fileName = metaVar->val;
}
if(tableName != NULL)
{
verbose(3, "tableName:%s\n",tableName);
if(fileName == NULL || startsWithWordByDelimiter(tableName,'.',fileName))
{
metaObj->obj = cloneString(tableName);
metaObj->objType = otTable;
}
}
else if(fileName != NULL)
{
verbose(3, "fileName:%s\n",fileName);
// NOTE: that the file object is the root of the name, so that file.fastq.gz = file.fastq
metaObj->obj = cloneFirstWordByDelimiter(fileName,'.');
metaObj->objType = otFile;
}
}
if(metaObj->obj == NULL)
{
errAbort("No obj found. This is not properly formatted metadata:\n\t%s\n",line);
//metaObjsFree(&metaObj);
//return NULL;
}
if(metaObj->objType == otUnknown) // NOTE: defaulting to table
{
metaObj->objType = otTable;
}
slReverse(&(metaObj->vars));
verbose(3, "metadataLineParse() obj=%s(%s) %s(%s)=%s\n",
metaObj->obj, metaObjTypeEnumToString(metaObj->objType),metaObj->vars->var,metaVarTypeEnumToString(metaObj->vars->varType),metaObj->vars->val);
return metaObj;
}
struct metaByVar *metaByVarsLineParse(char *line)
/* Parses a line of "var1=val1 var2=val2 into a metaByVar object for queries. */
{
int thisWord = 0;
struct metaByVar *metaByVars = NULL;
struct metaByVar *rootVar = NULL;
struct metaLimbVal *limbVal = NULL;
char *cloneLine = cloneString(line);
struct hash* varHash; // There must not be multiple occurrances of the same var
// initial chop and determine if this looks like metadata
int count = chopByWhiteRespectDoubleQuotes(cloneLine,NULL,0);
char **words = needMem(sizeof(char *) * count);
count = chopByWhiteRespectDoubleQuotes(cloneLine,words,count);
verbose(3, "metaByVarsLineParse() word count:%d\n\t%s\n",count,line);
// Get obj and figure out if this is a delete line
varHash = hashNew(0);
// All words are expected to be var=val pairs!
for(thisWord=0;thisWord<count;thisWord++)
{
if(strchr(words[thisWord], '=') == NULL)
{
errAbort("Expected 'var=val' but found '%s'. This is not properly formatted metadata:\n\t%s\n",words[thisWord],line);
//metaObjsFree(&metaObj);
//return NULL;
}
AllocVar(rootVar);
char *var = cloneNextWordByDelimiter(&(words[thisWord]),'=');
char *val = cloneString(words[thisWord]);
struct metaByVar *oldVar = (struct metaByVar *)hashFindVal(varHash, var);
if(oldVar)
{ // FIXME: Could build this for 'or' queries!
verbose(1, "The same variable appears twice: %s=%s and %s=%s. Ignoring second value.\n",
oldVar->var,oldVar->vals->val,var,val);
freeMem(var);
freeMem(val);
}
else
{
AllocVar(rootVar);
rootVar->var = var;
AllocVar(limbVal);
limbVal->val = val;
rootVar->vals = limbVal;
hashAdd(varHash, rootVar->var, rootVar);
slAddHead(&metaByVars,rootVar);
}
}
freeMem(words);
slReverse(&metaByVars);
verbose(3, "metaByVarsLineParse() parsed:%d first: %s=%s.\n",
slCount(metaByVars->vals),metaByVars->var,metaByVars->vals->val);
return metaByVars;
}
// ------ Loading from args, hashes and tdb ------
struct metaByVar*metaByVarCreate(char *var, char *varType,char *val)
/* Creates a singular var=val pair struct for metadata queries. */
{
struct metaByVar *metaByVar = NULL;
if(var == NULL)
errAbort("Need variable to create metaByVar query object.\n");
AllocVar(metaByVar);
metaByVar->var = cloneString(var);
metaByVar->varType = (varType==NULL?vtUnknown:metaVarTypeStringToEnum(varType));
if(val != NULL)
{
struct metaLimbVal * limbVal;
AllocVar(limbVal);
limbVal->val = cloneString(val);
metaByVar->vals = limbVal; // Only one
}
return metaByVar;
}
struct metaObj *metaObjCreate(char *obj,char *type,char *var, char *varType,char *val)
/* Creates a singular metaObj query object based on obj and all other optional params. */
{
struct metaObj *metaObj = NULL;
if(obj == NULL)
errAbort("Need obj to create metaObj query object.\n");
AllocVar(metaObj);
metaObj->obj = cloneString(obj);
metaObj->objType = (type==NULL?otUnknown:metaObjTypeStringToEnum(type));
if(var != NULL)
{
struct metaVar * metaVar;
AllocVar(metaVar);
metaVar->var = cloneString(var);
metaVar->varType = (varType==NULL?vtUnknown:metaVarTypeStringToEnum(varType));
if(val != NULL)
metaVar->val = cloneString(val);
metaObj->vars = metaVar; // Only one
}
return metaObj;
}
struct metaObj *metaObjsLoadFromHashes(struct hash *objsHash)
// Load all metaObjs from a file containing metadata formatted lines
{
struct metaObj *metaObjs = NULL;
struct hashEl* objEl = NULL;
struct hashCookie objCookie = hashFirst(objsHash);
while((objEl = hashNext(&objCookie)) != NULL)
{
struct metaObj *metaObj;
AllocVar(metaObj);
metaObj->obj = cloneString(objEl->name);
metaObj->varHash = hashNew(0);
struct hash *hashedVars = objEl->val;
struct hashCookie varCookie = hashFirst(hashedVars);
struct hashEl* varEl = NULL;
while((varEl = hashNext(&varCookie)) != NULL)
{
if(sameString(varEl->name,"metaObject"))
continue;
if(sameString(varEl->name,"objType"))
metaObj->objType = metaObjTypeStringToEnum(varEl->val);
else
{
struct metaVar * metaVar;
AllocVar(metaVar);
metaVar->var = cloneString(varEl->name);
metaVar->varType = vtTxt; // FIXME: binary?
metaVar->val = cloneString(varEl->val);
hashAdd(metaObj->varHash, metaVar->var, metaVar); // pointer to struct to resolve type
slAddHead(&(metaObj->vars),metaVar);
}
}
slSort(&(metaObj->vars),&metaVarCmp); // Should be in determined order
slAddHead(&metaObjs,metaObj);
}
slSort(&metaObjs,&metaObjCmp); // Should be in determined order
return metaObjs;
}
-static struct metaObj *metadataForTableFromTdb(struct trackDb *tdb)
-// Returns the metadata for a table from a tdb setting.
-{
-metadata_t *metadata = metadataSettingGet(tdb);
-// convert to a metaObj
-struct metaObj *metaObj = NULL;
-AllocVar(metaObj);
-metaObj->obj = tdb->tableName;
-metaObj->objType = otTable;
-metaObj->varHash = hashNew(0);
-
-int ix =0;
-for(;ix<metadata->count;ix++)
- {
- struct metaVar *metaVar = NULL;
- AllocVar(metaVar);
- metaVar->var = metadata->tags[ix];
- metaVar->varType = vtTxt;
- metaVar->val = metadata->values[ix];
- hashAdd(metaObj->varHash, metaVar->var, metaVar); // pointer to struct to resolve type
- slAddHead(&(metaObj->vars),metaVar);
- }
-slSort(&(metaObj->vars),&metaVarCmp); // Should be in determined order
-metadataFree(&metadata);
-return metaObj;
-}
-
-struct metaObj *metadataForTable(char *db,struct trackDb *tdb,char *table)
-// Returns the metadata for a table. Either tdb or table must be provided
-{
-struct sqlConnection *conn = sqlConnect(db);
-char *metaTbl = metaTblName(conn,TRUE); // Look for sandbox name first
-struct metaObj *metaObj = NULL;
-if(tdb != NULL && tdb->tableName != NULL)
- table = tdb->tableName;
-if(metaTbl != NULL)
- metaObj = metaObjQueryByObj(conn,metaTbl,table,NULL);
-sqlDisconnect(&conn);
-
-if(metaObj == NULL && tdb != NULL)
- return metadataForTableFromTdb(tdb);
-
-return metaObj;
-}
-
// ------ Loading from files ------
struct metaObj *metaObjsLoadFromFormattedFile(char *fileName,boolean *validated)
// Load all metaObjs from a file containing metadata formatted lines
{
struct metaObj *metaObjs = NULL;
struct lineFile *lf = lineFileOpen(fileName, TRUE);
char *line;
while (lineFileNext(lf, &line,NULL))
{
if(startsWithWord("metaObject",line))
{
// This is the RA style file!!
lineFileClose(&lf);
return metaObjsLoadFromRAFile(fileName,validated);
}
struct metaObj *metaObj = metadataLineParse(line);
if(metaObj == NULL)
{
metaObjsFree(&metaObjs);
return NULL;
}
slAddHead(&metaObjs,metaObj);
}
lineFileClose(&lf);
slReverse(&metaObjs); // Go ahead and keep this in file order
if(validated)
*validated = FALSE;
return metaObjs;
}
#define METATBL_MAGIC_PREFIX "# MAGIC: "
struct metaObj *metaObjsLoadFromRAFile(char *fileName,boolean *validated)
// Load all metaObjs from a file containing RA formatted 'metaObjects'
{
struct hash *mdHash = raReadAll(fileName, "metaObject");
if(mdHash == NULL)
{
verbose(1,"Missing, empty or badly formated RA file:%s\n",fileName);
return NULL;
}
struct metaObj *metaObjs = metaObjsLoadFromHashes(mdHash);
hashFree(&mdHash);
// Try to validate file
if(validated)
{
*validated = FALSE;
struct lineFile *lf = lineFileOpen(fileName, TRUE);
char *line = lineFileSkipToLineStartingWith(lf,METATBL_MAGIC_PREFIX,1000000);
if(line != NULL)
{
int fileMagic = atoi(line+strlen(METATBL_MAGIC_PREFIX));
int objsMagic = metaObjCRC(metaObjs);
verbose(3,"Objects magic: %d Files magic: %d (%s)\n",objsMagic,fileMagic,line+strlen(METATBL_MAGIC_PREFIX));
*validated = (fileMagic == objsMagic);
}
else
verbose(3,"Can't find magic number on this file.\n");
}
return metaObjs;
}
// ------ Table name and creation ------
#define METATBL_SPEC_LOCATION "/cluster/bin/sqlCreate/metaTbl.sql"
void metaTblReCreate(struct sqlConnection *conn,char *tblName,boolean testOnly)
// Creates ore Recreates the named metaTbl.
{
if(sqlTableExists(conn,tblName))
verbose(2, "Table '%s' already exists. It will be recreated.\n",tblName);
char *sql = NULL;
readInGulp(METATBL_SPEC_LOCATION, &sql, NULL);
char *pos = strchr(sql, ';');
if ( pos != NULL)
*pos = 0;
char *oldSql = cloneString(sql);
pos = stringIn("CREATE TABLE ", oldSql);
if (pos == NULL)
errAbort("Can't find CREATE TABLE in %s\n", METATBL_SPEC_LOCATION);
nextWord(&pos);
nextWord(&pos);
char *oldName = nextWord(&pos);
if(differentWord(oldName, tblName))
{
char *saveSql = cloneString(sql);
freeMem(sql);
sql = replaceChars(saveSql, oldName, tblName);
freeMem(saveSql);
}
freeMem(oldSql);
verbose(2, "Requesting table creation:\n\t%s;\n", sql);
if(!testOnly)
sqlRemakeTable(conn,tblName, sql);
freeMem(sql);
}
char*metaTblName(struct sqlConnection *conn,boolean mySandBox)
// returns the metaTbl name or NULL if conn supplied but the table doesn't exist
{
char *tblName = NULL;
char *root = NULL;
char *sand = NULL;
char *name = cfgOption("db.metaTbl");
if(name == NULL)
{
name = cfgOption("db.trackDb");
if(name == NULL)
root = cloneString(METATBL_DEFAULT_NAME);
}
// Divide name into root and sand
if(root == NULL)
{
char delimit = '_';
if((sand = strchr(name,delimit)) == NULL)
{
delimit = '-';
if((sand = strchr(name,delimit)) == NULL)
root = cloneString(name); // No sandBox portion
}
if(root == NULL) // There should be a sandbox portion
{
root = cloneNextWordByDelimiter(&name,delimit);
if(mySandBox && *name != 0)
sand = name;
}
}
// Since db.trackDb was used, make sure to swap it
if(sameWord("trackDb",root))
{
freeMem(root);
root = cloneString(METATBL_DEFAULT_NAME);
}
if(!mySandBox || sand == NULL)
tblName = root;
else
{
int size = strlen(root) + strlen(sand) + 2;
tblName = needMem(size);
safef(tblName,size,"%s_%s",root,sand);
}
// Test for table
if(conn != NULL && !sqlTableExists(conn,tblName))
{
if(sand == NULL || sameWord(tblName,root)) // Then try the root
return NULL;
freeMem(tblName);
tblName = root;
if(!sqlTableExists(conn,tblName))
return NULL;
}
return tblName;
}
// -------------- Updating the DB --------------
int metaObjsSetToDb(struct sqlConnection *conn,char *tableName,struct metaObj *metaObjs,boolean replace,boolean testOnly)
// Adds or updates metadata obj/var pairs into the named table. Returns total rows affected
{
char query[8192];
struct metaObj *metaObj;
struct metaVar *metaVar;
int count = 0;
if(tableName == NULL)
tableName = METATBL_DEFAULT_NAME;
if(!sqlTableExists(conn,tableName))
errAbort("metaObjsSetToDb attempting to update non-existent table named '%s'.\n",tableName);
for(metaObj = metaObjs;metaObj != NULL; metaObj = metaObj->next)
{
// Handle delete requests first
if(metaObj->deleteThis)
{
if(metaObj->vars == NULL) // deletes all
{
safef(query, sizeof(query),"%s where objName = '%s'",tableName,metaObj->obj);
int delCnt = sqlRowCount(conn,query);
if(delCnt>0)
{
safef(query, sizeof(query),
"delete from %s where objName = '%s'",tableName,metaObj->obj);
verbose(2, "Requesting delete of %d rows:\n\t%s;\n",delCnt, query);
if(!testOnly)
sqlUpdate(conn, query);
count += delCnt;
}
}
else // deletes selected vars
{
for(metaVar = metaObj->vars;metaVar != NULL; metaVar = metaVar->next)
{
safef(query, sizeof(query),
"select objName from %s where objName = '%s' and var = '%s'",
tableName,metaObj->obj,metaVar->var);
if(sqlExists(conn,query))
{
safef(query, sizeof(query),
"delete from %s where objName = '%s' and var = '%s'",
tableName,metaObj->obj,metaVar->var);
verbose(2, "Requesting delete of 1 row:\n\t%s;\n",query);
if(!testOnly)
sqlUpdate(conn, query);
count++;
}
}
}
continue; // Done with this metaObj
}
else if (replace) // If replace then clear out deadwood before inserting new vars
{
safef(query, sizeof(query),"%s where objName = '%s'",tableName,metaObj->obj);
int delCnt = sqlRowCount(conn,query);
if(delCnt>0)
{
safef(query, sizeof(query),
"delete from %s where objName = '%s'",tableName,metaObj->obj);
verbose(2, "Requesting replacement of %d rows:\n\t%s;\n",delCnt, query);
if(!testOnly)
sqlUpdate(conn, query);
count += delCnt;
}
}
// Now it is time for update or add!
for(metaVar = metaObj->vars;metaVar != NULL; metaVar = metaVar->next)
{
// Be sure to check for var existence first, then update
if (!replace)
{
struct metaObj *objExists = metaObjQueryByObj(conn,tableName,metaObj->obj,metaVar->var);
if(objExists)
{
if(differentString(metaVar->val,objExists->vars->val)
|| metaVar->varType != objExists->vars->varType)
{
safef(query, sizeof(query),
"update %s set varType = '%s', val = '%s' where objName = '%s' and var = '%s'",
tableName,
metaVarTypeEnumToString(metaVar->varType),sqlEscapeString(metaVar->val), // FIXME: binary val?
metaObj->obj,metaVar->var);
verbose(2, "Requesting update of 1 row:\n\t%s;\n",query);
if(!testOnly)
sqlUpdate(conn, query);
count++;
}
metaObjsFree(&objExists);
continue; // The object was found/updated so done with it
}
}
// Finally ready to insert new vars
safef(query, sizeof(query),
"insert into %s values ( '%s','%s','%s','%s','%s')",
tableName,metaObj->obj,metaObjTypeEnumToString(metaObj->objType),
metaVar->var,metaVarTypeEnumToString(metaVar->varType),
sqlEscapeString(metaVar->val)); // FIXME: binary val?
verbose(2, "Requesting insert of one row:\n\t%s;\n",query);
if(!testOnly)
sqlUpdate(conn, query);
count++;
}
}
return count;
}
// ------------------ Querys -------------------
struct metaObj *metaObjQuery(struct sqlConnection *conn,char *table,struct metaObj *metaObj)
// Query the metadata table by obj and optional vars and vals in metaObj struct. If metaObj is NULL query all.
// Returns new metaObj struct fully populated and sorted in obj,var order.
{
// select objName,var,val where (var= [and val=]) or ([var= and] val=) order by objName,var
boolean buildHash = TRUE;
if(table == NULL)
table = METATBL_DEFAULT_NAME;
if(!sqlTableExists(conn,table))
return NULL;
struct dyString *dy = newDyString(4096);
dyStringPrintf(dy, "select objName,objType,var,varType,val from %s", table);
if(metaObj != NULL && metaObj->obj != NULL)
{
dyStringPrintf(dy, " where objName = '%s'", metaObj->obj);
struct metaVar *metaVar;
for(metaVar=metaObj->vars;metaVar!=NULL;metaVar=metaVar->next)
{
if(metaVar==metaObj->vars)
dyStringPrintf(dy, " and (");
else
dyStringPrintf(dy, " or ");
if(metaVar->var != NULL && metaVar->val != NULL)
dyStringPrintf(dy, "(var = '%s' and val = '%s')", metaVar->var, sqlEscapeString(metaVar->val));
else if(metaVar->var != NULL)
dyStringPrintf(dy, "var = '%s'", metaVar->var);
else if(metaVar->val != NULL)
dyStringPrintf(dy, "val = '%s'", sqlEscapeString(metaVar->val));
else
errAbort("metaObjQuery has empty metaVar struct.\n");
buildHash = FALSE; // too few variables
}
if(metaObj->vars != NULL)
dyStringPrintf(dy, ")");
}
dyStringPrintf(dy, " order by objName, var");
verbose(3, "Requesting query:\n\t%s;\n",dyStringContents(dy));
struct metaTbl *metaTbl = metaTblLoadByQuery(conn, dyStringCannibalize(&dy));
struct metaObj *metaObjs = metaObjsLoadFromMemory(&metaTbl,buildHash);
verbose(3, "Returned %d object(s) with %d var(s).\n",
metaObjCount(metaObjs,TRUE),metaObjCount(metaObjs,FALSE));
return metaObjs;
}
struct metaObj *metaObjQueryByObj(struct sqlConnection *conn,char *table,char *obj,char *var)
// Query a single metadata object and optional var from a table (default metaTbl).
{
if(obj == NULL)
return metaObjQuery(conn,table,NULL);
struct metaObj *queryObj = metaObjCreate(obj,NULL,var,NULL,NULL);
struct metaObj *resultObj = metaObjQuery(conn,table,queryObj);
metaObjsFree(&queryObj);
return resultObj;
}
struct metaByVar *metaByVarsQuery(struct sqlConnection *conn,char *table,struct metaByVar *metaByVars)
// Query the metadata table by one or more var=val pairs to find the distinct set of objs that satisfy ANY conditions.
// Returns new metaByVar struct fully populated and sorted in var,val,obj order.
{
// select objName,var,val where (var= [and val in (val1,val2)]) or (var= [and val in (val1,val2)]) order by var,val,objName
if(table == NULL)
table = METATBL_DEFAULT_NAME;
if(!sqlTableExists(conn,table))
return NULL;
struct dyString *dy = newDyString(4096);
dyStringPrintf(dy, "select distinct objName,objType,var,varType,val from %s", table);
struct metaByVar *rootVar;
for(rootVar=metaByVars;rootVar!=NULL;rootVar=rootVar->next)
{
if(rootVar==metaByVars)
dyStringPrintf(dy, " where ");
else
dyStringPrintf(dy, " OR ");
dyStringPrintf(dy, "(var = '%s'", rootVar->var);
struct metaLimbVal *limbVal;
for(limbVal=rootVar->vals;limbVal!=NULL;limbVal=limbVal->next)
{
if(limbVal==rootVar->vals)
dyStringPrintf(dy, " and val in (");
else
dyStringPrintf(dy, ",");
dyStringPrintf(dy, "'%s'", sqlEscapeString(limbVal->val));
}
if(rootVar->vals != NULL)
dyStringPrintf(dy, ")");
dyStringPrintf(dy, ")");
}
dyStringPrintf(dy, " order by var, val, objName");
verbose(3, "Requesting query:\n\t%s;\n",dyStringContents(dy));
struct metaTbl *metaTbl = metaTblLoadByQuery(conn, dyStringCannibalize(&dy));
verbose(3, "rows (vars) returned: %d\n",slCount(metaTbl));
struct metaByVar *metaByVarsFromMem = metaByVarsLoadFromMemory(&metaTbl,TRUE);
verbose(3, "Returned %d vars(s) with %d val(s) with %d object(s).\n",
metaByVarCount(metaByVarsFromMem,TRUE ,FALSE),
metaByVarCount(metaByVarsFromMem,FALSE,TRUE ),
metaByVarCount(metaByVarsFromMem,FALSE,FALSE));
return metaByVarsFromMem;
}
struct metaByVar *metaByVarQueryByVar(struct sqlConnection *conn,char *table,char *varName,char *val)
// Query a single metadata variable and optional val from a table (default metaTbl) for searching val->obj.
{
if(varName == NULL)
return metaByVarsQuery(conn,table,NULL);
struct metaByVar *queryVar = metaByVarCreate(varName,NULL,val);
struct metaByVar *resultVar = metaByVarsQuery(conn,table,queryVar);
metaByVarsFree(&queryVar);
return resultVar;
}
struct metaObj *metaObjsQueryByVars(struct sqlConnection *conn,char *table,struct metaByVar *metaByVars)
// Query the metadata table by one or more var=val pairs to find the distinct set of objs that satisfy ALL conditions.
// Returns new metaObj struct fully populated and sorted in obj,var order.
{
// select objName,var,val where (var= [and val in (val1,val2)]) or (var= [and val in (val1,val2)]) order by objName,var
if(table == NULL)
table = METATBL_DEFAULT_NAME;
if(!sqlTableExists(conn,table))
return NULL;
struct dyString *dy = newDyString(4096);
dyStringPrintf(dy, "select distinct objName,objType,var,varType,val from %s", table);
struct metaByVar *rootVar;
boolean gotVar = FALSE;
for(rootVar=metaByVars;rootVar!=NULL;rootVar=rootVar->next)
{
if(!gotVar)
{
dyStringPrintf(dy, " where objName in ");
gotVar=TRUE;
}
else
dyStringPrintf(dy, " AND objName in ");
dyStringPrintf(dy, "(select objName from %s where var = '%s'", table, rootVar->var);
struct metaLimbVal *limbVal;
boolean gotVal = FALSE;
for(limbVal=rootVar->vals;limbVal!=NULL;limbVal=limbVal->next)
{
if(limbVal->val == NULL || strlen(limbVal->val) < 1)
continue;
if(!gotVal)
{
dyStringPrintf(dy, " and val in (");
gotVal=TRUE;
}
else
dyStringPrintf(dy, ",");
dyStringPrintf(dy, "'%s'", sqlEscapeString(limbVal->val));
}
if(gotVal)
dyStringPrintf(dy, ")");
dyStringPrintf(dy, ")");
}
dyStringPrintf(dy, " order by objName, var");
verbose(3, "Requesting query:\n\t%s;\n",dyStringContents(dy));
struct metaTbl *metaTbl = metaTblLoadByQuery(conn, dyStringCannibalize(&dy));
verbose(3, "rows (vars) returned: %d\n",slCount(metaTbl));
struct metaObj *metaObjs = metaObjsLoadFromMemory(&metaTbl,TRUE);
verbose(3, "Returned %d object(s) with %d var(s).\n",
metaObjCount(metaObjs,TRUE),metaObjCount(metaObjs,FALSE));
return metaObjs;
}
// ----------- Printing and Counting -----------
void metaObjPrint(struct metaObj *metaObjs,boolean raStyle)
// prints objs and var=val pairs as formatted metadata lines or ra style
{
// Single line:
// metadata iLoveLucy table lucy=ricky ethyl=fred
// ra style
// metadata iLoveLucy table
// lucy ricky
// ethy fred
// TODO: Expand for mutilple var types; strip quotes from vals on ra style
struct metaObj *metaObj = NULL;
for(metaObj=metaObjs;metaObj!=NULL;metaObj=metaObj->next)
{
if(metaObj->obj == NULL)
continue;
printf("%s %s",(raStyle?"metaObject":"metadata"),metaObj->obj);
if(metaObj->deleteThis)
printf(" delete");
else
{
if(raStyle)
printf("\n objType %s",metaObjTypeEnumToString(metaObj->objType));
else
printf(" %s",metaObjTypeEnumToString(metaObj->objType));
}
struct metaVar *metaVar = NULL;
for(metaVar=metaObj->vars;metaVar!=NULL;metaVar=metaVar->next)
{
if(metaVar->var != NULL)
{
if(raStyle)
printf("\n %s ",metaVar->var);
else
printf(" %s=",metaVar->var);
if(metaVar->val != NULL)
{
if(metaVar->varType == vtBinary)
printf("binary");
else
printf("%s",metaVar->val);
}
}
}
printf("%s",(raStyle?"\n\n":"\n"));
}
if(raStyle) // NOTE: currently only supporting validation of RA files
printf("%s%d\n",METATBL_MAGIC_PREFIX,metaObjCRC(metaObjs));
}
void metaByVarPrint(struct metaByVar *metaByVars,boolean raStyle)
// prints var=val pairs and objs that go with them single lines or ra style
{
// Single line:
// metaVariable lucy=ethyl bestFriends lifePartners
// metaVariable lucy=ricky iLoveLucy divorces
// NOT QUITE ra style
// metaVariable lucy
// ethyl
// bestFriends
// lifePartners
// ricky
// iLoveLucy
// divorces
// TODO: Expand for mutilple var types; strip quotes from vals on ra style
struct metaByVar *rootVar = NULL;
for(rootVar=metaByVars;rootVar!=NULL;rootVar=rootVar->next)
{
if(rootVar->var == NULL)
continue;
boolean first = TRUE;
struct metaLimbVal *limbVal = NULL;
for(limbVal=rootVar->vals;limbVal!=NULL;limbVal=limbVal->next)
{
if(limbVal->val == NULL)
continue;
if(first) // first val for this var
{
printf("metaVariable %s",rootVar->var);
first = FALSE;
}
if(rootVar->varType == vtBinary)
printf("%sbinary",(raStyle ? "\n ":"="));
else
printf("%s%s",(raStyle ? "\n ":"="),limbVal->val);
struct metaLeafObj *leafObj = NULL;
for(leafObj=limbVal->objs;leafObj!=NULL;leafObj=leafObj->next)
{
if(leafObj->obj == NULL)
continue;
printf("%s%s",(raStyle?"\n ":" "),leafObj->obj);
}
printf("\n");
}
}
}
int metaObjCount(struct metaObj *metaObjs,boolean objs)
// returns the count of vars belonging to this obj or objs;
{
int count = 0;
struct metaObj *metaObj = NULL;
for(metaObj=metaObjs;metaObj!=NULL;metaObj=metaObj->next)
{
if(metaObj->obj == NULL)
continue;
if(objs)
count++;
else
{
struct metaVar *metaVar = NULL;
for(metaVar=metaObj->vars;metaVar!=NULL;metaVar=metaVar->next)
{
if(metaVar->var != NULL && metaVar->val != NULL)
count++;
}
}
}
return count;
}
int metaByVarCount(struct metaByVar *metaByVars,boolean vars, boolean vals)
// returns the count of objs belonging to this set of vars;
{
int count = 0;
struct metaByVar *rootVar = NULL;
for(rootVar=metaByVars;rootVar!=NULL;rootVar=rootVar->next)
{
if(rootVar->var == NULL)
continue;
if(vars)
count++;
else
{
struct metaLimbVal *limbVal = NULL;
for(limbVal=rootVar->vals;limbVal!=NULL;limbVal=limbVal->next)
{
if(limbVal->val == NULL)
continue;
if(vals)
count++;
else
{
struct metaLeafObj *leafObj = NULL;
for(leafObj=limbVal->objs;leafObj!=NULL;leafObj=leafObj->next)
{
if(leafObj->obj != NULL)
count++;
}
}
}
}
}
return count;
}
// ----------------- Utilities -----------------
-char *metadataFindValue(struct metaObj *metaObj, char *var)
+char *metaObjFindValue(struct metaObj *metaObj, char *var)
// Finds the val associated with the var or retruns NULL
{
if (metaObj == NULL)
return NULL;
struct metaVar *metaVar = NULL;
if(metaObj->varHash != NULL)
metaVar = hashFindVal(metaObj->varHash,var);
else
{
for(metaVar=metaObj->vars;metaVar!=NULL;metaVar=metaVar->next)
{
if(sameOk(var,metaVar->var))
break;
}
}
if(metaVar == NULL)
return NULL;
return metaVar->val;
}
boolean metaObjContains(struct metaObj *metaObj, char *var, char *val)
// Returns TRUE if object contains var, val or both
{
if (metaObj == NULL)
return FALSE;
if(var != NULL)
{
- char *foundVal = metadataFindValue(metaObj,var);
+ char *foundVal = metaObjFindValue(metaObj,var);
if(foundVal == NULL)
return FALSE;
if(val == NULL)
return TRUE;
return sameOk(foundVal,val);
}
struct metaVar *metaVar = NULL;
for(metaVar=metaObj->vars;metaVar!=NULL;metaVar=metaVar->next)
{
if(differentStringNullOk(var,metaVar->var) != 0)
continue;
if(differentStringNullOk(val,metaVar->val) != 0)
continue;
return TRUE;
}
return FALSE;
}
boolean metaByVarContains(struct metaByVar *metaByVar, char *val, char *obj)
// Returns TRUE if var contains val, obj or both
{
if (metaByVar != NULL)
{
struct metaLimbVal *limbVal = NULL;
struct metaLeafObj *leafObj = NULL;
if(metaByVar->valHash != NULL && val != NULL)
{
limbVal = hashFindVal(metaByVar->valHash,val);
if(limbVal == NULL || limbVal->val == NULL)
return FALSE;
if(limbVal->objHash != NULL && obj != NULL)
{
leafObj = hashFindVal(limbVal->objHash,obj);
if(leafObj == NULL)
return FALSE;
return sameOk(leafObj->obj,obj);
}
}
for(limbVal=metaByVar->vals;limbVal!=NULL;limbVal=limbVal->next)
{
if(differentStringNullOk(val,limbVal->val) != 0)
continue;
for(leafObj=limbVal->objs;leafObj!=NULL;leafObj=leafObj->next)
{
if(differentStringNullOk(obj,leafObj->obj) != 0)
continue;
return TRUE;
}
}
}
return FALSE;
}
void metaObjReorderVars(struct metaObj *metaObjs, char *vars,boolean back)
// Reorders vars list based upon list of vars "cell antibody treatment". Send to front or back.
{
//char *words[48];
char *cloneLine = cloneString(vars);
int count = chopByWhite(cloneLine,NULL,0);
char **words = needMem(sizeof(char *) * count);
count = chopByWhite(cloneLine,words,count);
//int count = chopLine(cloneLine,words);
struct metaObj *metaObj = NULL;
for( metaObj=metaObjs; metaObj!=NULL; metaObj=metaObj->next )
{
int ix;
struct metaVar *orderedVars = NULL;
struct metaVar **varsToReorder = needMem(sizeof(struct metaVar *) * count);
struct metaVar *metaVar = NULL;
while((metaVar = slPopHead(&(metaObj->vars))) != NULL)
{
ix = stringArrayIx(metaVar->var,words,count);
if(ix < 0)
slAddHead(&orderedVars,metaVar);
else
varsToReorder[ix] = metaVar;
}
if(back) // add to front of backward list
{
for( ix=0; ix<count; ix++ )
{
if(varsToReorder[ix] != NULL)
slAddHead(&orderedVars,varsToReorder[ix]);
}
}
slReverse(&orderedVars);
if(!back) // Add to front of forward list
{
for( ix=count-1; ix>=0; ix-- )
{
if(varsToReorder[ix] != NULL)
slAddHead(&orderedVars,varsToReorder[ix]);
}
}
metaObj->vars = orderedVars;
freeMem(varsToReorder);
}
freeMem(words);
}
void metaObjRemoveVars(struct metaObj *metaObjs, char *vars)
// Prunes list of vars for an object, freeing the memory. Doesn't touch DB.
{
char *cloneLine = NULL;
int count = 0;
char **words = NULL;
-if(vars == NULL) // prune all!
- {
- }
-else
+if(vars != NULL)
{
cloneLine = cloneString(vars);
count = chopByWhite(cloneLine,NULL,0);
words = needMem(sizeof(char *) * count);
count = chopByWhite(cloneLine,words,count);
}
struct metaObj *metaObj = NULL;
for( metaObj=metaObjs; metaObj!=NULL; metaObj=metaObj->next )
{
int ix;
struct metaVar *keepTheseVars = NULL;
+ if(count == 0 && metaObj->varHash != NULL)
+ hashFree(&metaObj->varHash);
+
struct metaVar *metaVar = NULL;
while((metaVar = slPopHead(&(metaObj->vars))) != NULL)
{
if(count == 0)
ix = 1;
else
ix = stringArrayIx(metaVar->var,words,count);
if(ix < 0)
slAddHead(&keepTheseVars,metaVar);
else
+ {
+ if(count != 0 && metaObj->varHash != NULL)
+ hashRemove(metaObj->varHash, metaVar->var);
+
metaVarFree(&metaVar);
}
+ }
if(keepTheseVars != NULL)
slReverse(&keepTheseVars);
metaObj->vars = keepTheseVars;
}
if(words != NULL)
freeMem(words);
}
void metaObjTransformToUpdate(struct metaObj *metaObjs, char *var, char *varType,char *val,boolean deleteThis)
/* Turns one or more metaObjs into the stucture needed to add/update or delete. */
{
-metaObjRemoveVars(metaObjs,NULL); // First drop all vars currently defined.
-
struct metaObj *metaObj = NULL;
for( metaObj=metaObjs; metaObj!=NULL; metaObj=metaObj->next )
{
metaObj->deleteThis = deleteThis;
+ if(metaObj->varHash != NULL)
+ hashFree(&metaObj->varHash);
+
+ struct metaVar *metaVar = NULL;
+ while((metaVar = slPopHead(&(metaObj->vars))) != NULL)
+ metaVarFree(&metaVar);
+
if(var != NULL)
{
- struct metaVar * metaVar;
AllocVar(metaVar);
metaVar->var = cloneString(var);
metaVar->varType = (varType==NULL?vtUnknown:metaVarTypeStringToEnum(varType));
if(val != NULL)
metaVar->val = cloneString(val);
metaObj->vars = metaVar; // Only one
}
}
}
-int metaObjCRC(struct metaObj *metaObjs)
-// returns a summ of all individual CRC values of all metObj strings
+struct metaObj *metaObjClone(struct metaObj *metaObj)
+// Clones a single metaObj, including hash and maintining order
{
-int crc = 0;
-struct metaObj *metaObj = NULL;
-for(metaObj=metaObjs;metaObj!=NULL;metaObj=metaObj->next)
+if(metaObj == NULL)
+ return NULL;
+
+struct metaObj *newObj;
+AllocVar(newObj);
+
+if(metaObj->obj != NULL)
+ newObj->obj = cloneString(metaObj->obj);
+newObj->objType = metaObj->objType;
+newObj->deleteThis = metaObj->deleteThis;
+if(metaObj->vars != NULL)
{
- if(metaObj->obj != NULL)
- crc += hashCrc(metaObj->obj);
+ if(metaObj->varHash != NULL)
+ newObj->varHash = hashNew(0);
struct metaVar *metaVar = NULL;
- for(metaVar=metaObj->vars;metaVar!=NULL;metaVar=metaVar->next)
+ for(metaVar = metaObj->vars; metaVar != NULL; metaVar = metaVar->next )
{
+ struct metaVar *newVar = NULL;
+ AllocVar(newVar);
if(metaVar->var != NULL)
- crc += hashCrc(metaVar->var);
- if(metaVar->varType == vtTxt && metaVar->val != NULL)
- crc += hashCrc(metaVar->val);
+ newVar->var = cloneString(metaVar->var);
+ if(metaVar->val != NULL)
+ newVar->val = cloneString(metaVar->val);
+ newVar->varType = metaVar->varType;
+ if(newVar->var != NULL && newVar->val != NULL)
+ hashAdd(newObj->varHash, newVar->var, newVar); // pointer to struct to resolve type
+ slAddHead(&(newObj->vars),newVar);
}
+ slReverse(&(newObj->vars));
}
-
-return crc;
+return newObj;
}
// --------------- Free at last ----------------
void metaObjsFree(struct metaObj **metaObjsPtr)
// Frees one or more metadata objects and any contained metaVars. Will free any hashes as well.
{
if(metaObjsPtr != NULL && *metaObjsPtr != NULL)
{
// free all roots
struct metaObj *metaObj = NULL;
while((metaObj = slPopHead(metaObjsPtr)) != NULL)
{
// Free hash first (shared memory)
hashFree(&(metaObj->varHash));
// free all leaves
struct metaVar *metaVar = NULL;
while((metaVar = slPopHead(&(metaObj->vars))) != NULL)
metaVarFree(&metaVar);
// The rest of root
freeMem(metaObj->obj);
freeMem(metaObj);
}
freez(metaObjsPtr);
}
}
void metaByVarsFree(struct metaByVar **metaByVarsPtr)
// Frees one or more metadata vars and any contained vals and objs. Will free any hashes as well.
{
if(metaByVarsPtr != NULL && *metaByVarsPtr != NULL)
{
// free all roots
struct metaByVar *rootVar = NULL;
while((rootVar = slPopHead(metaByVarsPtr)) != NULL)
{
// Free hash first (shared memory)
hashFree(&(rootVar->valHash));
// free all limbs
struct metaLimbVal *limbVal = NULL;
while((limbVal = slPopHead(&(rootVar->vals))) != NULL)
metaLimbValFree(&limbVal);
// The rest of root
if(rootVar->var)
freeMem(rootVar->var);
freeMem(rootVar);
}
freez(metaByVarsPtr);
}
}
-// TODO: Print formatted metadata lines!
+// ----------------- CGI specific routines for use with tdb -----------------
+#define METATBL_NOT_FOUND ((struct metaObj *)-666)
+#define METADATA_NOT_FOUND ((struct metaObj *)-999)
+#define METATBL_OBJ_KEY "metaObj"
+static struct metaObj *metadataForTableFromTdb(struct trackDb *tdb)
+// Returns the metadata for a table from a tdb setting.
+{
+metadata_t *metadata = metadataSettingGet(tdb);
+if(metadata == NULL)
+ {
+ tdbExtrasAddOrUpdate(tdb,METATBL_OBJ_KEY,METADATA_NOT_FOUND);
+ return NULL;
+ }
+// convert to a metaObj
+struct metaObj *metaObj = NULL;
+AllocVar(metaObj);
+metaObj->obj = cloneString(tdb->tableName);
+metaObj->objType = otTable;
+metaObj->varHash = hashNew(0);
+int ix =0;
+for(;ix<metadata->count;ix++)
+ {
+ struct metaVar *metaVar = NULL;
+ AllocVar(metaVar);
+ metaVar->var = cloneString(metadata->tags[ix]);
+ metaVar->varType = vtTxt;
+ metaVar->val = cloneString(metadata->values[ix]);
+ hashAdd(metaObj->varHash, metaVar->var, metaVar); // pointer to struct to resolve type
+ slAddHead(&(metaObj->vars),metaVar);
+ }
+slSort(&(metaObj->vars),&metaVarCmp); // Should be in determined order
+metadataFree(&metadata);
+
+// Save metaObj to trackDbSettings
+tdbExtrasAddOrUpdate(tdb,METATBL_OBJ_KEY,metaObj);
+
+return metaObj;
+}
+
+struct metaObj *metadataForTable(char *db,struct trackDb *tdb,char *table)
+// Returns the metadata for a table. NEVER FREE THIS STRUCT!
+{
+struct metaObj *metaObj = NULL;
+
+// See of the metaObj was already built
+if(tdb != NULL)
+ {
+ metaObj = tdbExtrasGetOrDefault(tdb, METATBL_OBJ_KEY,NULL);
+ if(metaObj == METADATA_NOT_FOUND) // NOT in mtatbl, not in tdb metadata setting!
+ return NULL;
+ else if(metaObj == METATBL_NOT_FOUND) // looked metaTbl already and not found!
+ return metadataForTableFromTdb(tdb);
+ else if(metaObj != NULL)
+ {
+ return metaObj; // No reason to query the table again!
+ }
+ }
+
+struct sqlConnection *conn = sqlConnect(db);
+char *metaTbl = metaTblName(conn,TRUE); // Look for sandbox name first
+if(tdb != NULL && tdb->tableName != NULL)
+ table = tdb->tableName;
+if(metaTbl != NULL)
+ metaObj = metaObjQueryByObj(conn,metaTbl,table,NULL);
+sqlDisconnect(&conn);
+
+// save the metaObj for next time
+if(tdb)
+ {
+ if(metaObj != NULL)
+ tdbExtrasAddOrUpdate(tdb,METATBL_OBJ_KEY,metaObj);
+ else
+ {
+ tdbExtrasAddOrUpdate(tdb,METATBL_OBJ_KEY,METATBL_NOT_FOUND);
+ return metadataForTableFromTdb(tdb); // FIXME: metadata setting in TDB is soon to be obsolete
+ }
+ }
+
+// FIXME: Temporary to distinguish metaTbl metadata from trackDb metadata:
+metaObjRemoveVars(metaObj,"tableName");
+
+
+return metaObj;
+}
+
+char *metadataFindValue(struct trackDb *tdb, char *var)
+// Finds the val associated with the var or retruns NULL
+{
+struct metaObj *metaObj = tdbExtrasGetOrDefault(tdb, METATBL_OBJ_KEY,NULL);
+if(metaObj == METATBL_NOT_FOUND) // Note, only we if already looked for metaTbl (which requires db)
+ metaObj = metadataForTableFromTdb(tdb);
+if (metaObj == NULL || metaObj == METADATA_NOT_FOUND)
+ return NULL;
+
+return metaObjFindValue(metaObj,var);
+
+struct metaVar *metaVar = NULL;
+if(metaObj->varHash != NULL)
+ metaVar = hashFindVal(metaObj->varHash,var);
+else
+ {
+ for(metaVar=metaObj->vars;metaVar!=NULL;metaVar=metaVar->next)
+ {
+ if(sameOk(var,metaVar->var))
+ break;
+ }
+ }
+if(metaVar == NULL)
+ return NULL;
+
+return metaVar->val;
+}