src/hg/lib/metaTbl.c 1.3
1.3 2010/03/19 17:34:33 tdreszer
The most useful query yet: all objs that contain every var=val pair provided.
Index: src/hg/lib/metaTbl.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/lib/metaTbl.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -b -B -U 1000000 -r1.2 -r1.3
--- src/hg/lib/metaTbl.c 18 Mar 2010 23:36:05 -0000 1.2
+++ src/hg/lib/metaTbl.c 19 Mar 2010 17:34:33 -0000 1.3
@@ -1,1010 +1,1079 @@
/* 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 -------------------------------- */
+
+// ------- (static) convert from autoSql -------
+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->objName) )
+ {
+ // Finish last object before starting next!
+ if(metaObj!= NULL)
+ slReverse(&(metaObjs->vars));
+ // Start new object
+ AllocVar(metaObj);
+ metaObj->objName = 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);
+ }
+
+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(rootVar != NULL)
+ slReverse(&(rootVar->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)
+ 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->objName = thisRow->objName;
+ leafObj->objType = metaObjTypeStringToEnum(thisRow->objType);
+ freeMem(thisRow->objType);
+ if ( buildHashes )
+ hashAddUnique(limbVal->objHash, leafObj->objName, leafObj); // Pointer to struct to resolve type!
+ slAddHead(&(limbVal->objs),leafObj);
+
+ freeMem(thisRow);
+ }
+
+slReverse(&rootVars);
+
+return rootVars;
+}
+
+// -------------- 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";
}
}
+// ------ Loading files and parsing lines ------
struct metaObj *metadataLineParse(char *line)
/* Parses a single formatted metadata line into metaObj for updates or queries. */
{
char *words[256]; // A lot!
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,words,ArraySize(words));
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->objName = cloneString(words[thisWord++]);
verbose(3, "metadataLineParse() objName=%s\n",metaObj->objName);
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 objName delete... or objName 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);
freeMem(metaVar->var);
freeMem(metaVar->val);
freeMem(metaVar);
}
else
{
hashAdd(metaObj->varHash, metaVar->var, metaVar); // pointer to struct to resolve type
slAddHead(&(metaObj->vars),metaVar);
}
}
// Special for old style ENCODE metadata
if(metaObj->objName == 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(2, "tableName:%s\n",tableName);
if(fileName == NULL || startsWithWordByDelimiter(tableName,'.',fileName))
{
metaObj->objName = cloneString(tableName);
metaObj->objType = otTable;
}
}
else if(fileName != NULL)
{
verbose(2, "fileName:%s\n",fileName);
// NOTE: that the file object is the root of the name, so that file.fastq.gz = file.fastq
metaObj->objName = cloneFirstWordByDelimiter(fileName,'.');
metaObj->objType = otFile;
}
}
if(metaObj->objName == NULL)
{
errAbort("No objName 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(2, "metadataLineParse() objName=%s(%s) %s(%s)=%s\n",
metaObj->objName, metaObjTypeEnumToString(metaObj->objType),metaObj->vars->var,metaVarTypeEnumToString(metaObj->vars->varType),metaObj->vars->val);
return metaObj;
}
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->objName = 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 metaByVar *metaByVarsLineParse(char *line)
/* Parses a line of "var1=val1 var2=val2 into a metaByVar object for queries. */
{
char *words[256]; // A lot!
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,words,ArraySize(words));
verbose(3, "metaByVarsLineParse() word count:%d\n\t%s\n",count,line);
// Get objName 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);
}
}
slReverse(&metaByVars);
verbose(2, "metaByVarsLineParse() first: %s=%s\n",metaByVars->var,metaByVars->vals->val);
return metaByVars;
}
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 *metaObjsLoadFromFormattedFile(char *fileName)
// 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))
{
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
return metaObjs;
}
-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->objName) )
- {
- // Finish last object before starting next!
- if(metaObj!= NULL)
- slReverse(&(metaObjs->vars));
- // Start new object
- AllocVar(metaObj);
- metaObj->objName = 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);
- }
-
-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(rootVar != NULL)
- slReverse(&(rootVar->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)
- 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->objName = thisRow->objName;
- leafObj->objType = metaObjTypeStringToEnum(thisRow->objType);
- freeMem(thisRow->objType);
- if ( buildHashes )
- hashAddUnique(limbVal->objHash, leafObj->objName, leafObj); // Pointer to struct to resolve type!
- slAddHead(&(limbVal->objs),leafObj);
-
- freeMem(thisRow);
- }
-
-slReverse(&rootVars);
-
-return rootVars;
-}
-
+// -------------- Updating the DB --------------
int metaObjsSetToDb(struct sqlConnection *conn,char *tableName,struct metaObj *metaObjs,boolean replace)
// 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;
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->objName);
int delCnt = sqlRowCount(conn,query);
if(delCnt>0)
{
safef(query, sizeof(query),
"delete from %s where objName = '%s'",tableName,metaObj->objName);
verbose(2, "Delete of %d rows requested: %s\n",delCnt, query);
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->objName,metaVar->var);
if(sqlExists(conn,query))
{
safef(query, sizeof(query),
"delete from %s where objName = '%s' and var = '%s'",
tableName,metaObj->objName,metaVar->var);
verbose(2, "Requested: %s\n",query);
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->objName);
int delCnt = sqlRowCount(conn,query);
if(delCnt>0)
{
safef(query, sizeof(query),
"delete from %s where objName = '%s'",tableName,metaObj->objName);
verbose(2, "Replacing %d rows requested: %s\n",delCnt, query);
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->objName,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->objName,metaVar->var);
verbose(2, "Requested: %s\n",query);
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->objName,metaObjTypeEnumToString(metaObj->objType),
metaVar->var, metaVarTypeEnumToString(metaVar->varType),
sqlEscapeString(metaVar->val)); // FIXME: binary val?
verbose(2, "Requested: %s\n",query);
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.
-// Retruns new metaObj struct fully populated and sorted in obj,var order.
+// Returns new metaObj struct fully populated and sorted in obj,var order.
{
// select obj,var,val where (var= [and val=]) or ([var= and] val=) order by obj,var
boolean buildHash = TRUE;
struct dyString *dy = newDyString(4096);
if(table == NULL)
table = METATBL_DEFAULT_NAME;
dyStringPrintf(dy, "select objName,objType,var,varType,val from %s", table);
if(metaObj != NULL && metaObj->objName != NULL)
{
dyStringPrintf(dy, " where objName = '%s'", metaObj->objName);
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(2, "Query: %s\n",dyStringContents(dy));
struct metaTbl *metaTbl = metaTblLoadByQuery(conn, dyStringCannibalize(&dy));
+ verbose(2, "rows returned: %d\n",slCount(metaTbl));
return metaObjsLoadFromMemory(&metaTbl,buildHash);
}
struct metaObj *metaObjQueryByObj(struct sqlConnection *conn,char *table,char *objName,char *varName)
// Query a single metadata object and optional var from a table (default metaTbl).
{
if(objName == NULL)
return metaObjQuery(conn,table,NULL);
struct metaObj *queryObj = metaObjCreate(objName,NULL,varName,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 vars and vals in metaByVar struct. If metaByVar is NULL query all.
-// Retruns new metaByVar struct fully populated and sorted in var,val,obj order.
+// 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 var,val,obj where (var= [and val in (val1,val2)]) or (var= [and val in (val1,val2)]) order by var,val,obj
struct dyString *dy = newDyString(4096);
if(table == NULL)
table = METATBL_DEFAULT_NAME;
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, " 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(2, "Query: %s\n",dyStringContents(dy));
struct metaTbl *metaTbl = metaTblLoadByQuery(conn, dyStringCannibalize(&dy));
+ verbose(2, "rows returned: %d\n",slCount(metaTbl));
return metaByVarsLoadFromMemory(&metaTbl,TRUE);
}
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 var,val,obj where (var= [and val in (val1,val2)]) or (var= [and val in (val1,val2)]) order by var,val,obj
+ struct dyString *dy = newDyString(4096);
+ if(table == NULL)
+ table = METATBL_DEFAULT_NAME;
+ 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 objName in ");
+ else
+ dyStringPrintf(dy, " AND objName in ");
+ dyStringPrintf(dy, "(select objName from %s where var = '%s'", table, 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 objName, var");
+ verbose(2, "Query: %s\n",dyStringContents(dy));
+
+ struct metaTbl *metaTbl = metaTblLoadByQuery(conn, dyStringCannibalize(&dy));
+ verbose(2, "rows returned: %d\n",slCount(metaTbl));
+ return metaObjsLoadFromMemory(&metaTbl,TRUE);
+}
+
+
+// ----------- Printing and Counting -----------
void metaObjPrint(struct metaObj *metaObjs,boolean printLong)
// prints objs and var=val pairs as formatted metadata lines or long view
{
struct metaObj *metaObj = NULL;
for(metaObj=metaObjs;metaObj!=NULL;metaObj=metaObj->next)
{
if(metaObj->objName == NULL)
continue;
printf("metadata %s %s%s",metaObj->objName,
metaObjTypeEnumToString(metaObj->objType),(printLong?"\n\t":" "));
struct metaVar *metaVar = NULL;
for(metaVar=metaObj->vars;metaVar!=NULL;metaVar=metaVar->next)
{
if(metaVar->var != NULL && metaVar->val != NULL)
{
printf("%s=",metaVar->var);
if(metaVar->varType == vtBinary)
printf("binary%s",(printLong?"\n\t":" "));
else
printf("%s%s",metaVar->val,(printLong?"\n\t":" "));
}
}
printf("\n");
}
}
void metaByVarPrint(struct metaByVar *metaByVars,boolean printLong)
// prints var=val pairs and objs that go with them single lines or long view
{
struct metaByVar *rootVar = NULL;
for(rootVar=metaByVars;rootVar!=NULL;rootVar=rootVar->next)
{
if(rootVar->var == NULL)
continue;
struct metaLimbVal *limbVal = NULL;
for(limbVal=rootVar->vals;limbVal!=NULL;limbVal=limbVal->next)
{
if(limbVal->val == NULL)
continue;
printf("metaVariable %s=",rootVar->var);
if(rootVar->varType == vtBinary)
printf("binary%s",(printLong?"\n\t":" "));
else
printf("%s%s",limbVal->val,(printLong?"\n\t":" "));
struct metaLeafObj *leafObj = NULL;
for(leafObj=limbVal->objs;leafObj!=NULL;leafObj=leafObj->next)
{
if(leafObj->objName != NULL)
printf("%s%s",leafObj->objName,(printLong?"\n\t":" "));
}
}
printf("\n");
}
}
-int metaObjCount(struct metaObj *metaObjs)
+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->objName == 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)
+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->objName != NULL)
count++;
}
}
}
+ }
+ }
return count;
}
+// --------------- 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)
if(metaObj->varHash != NULL)
hashFree(&(metaObj->varHash));
// free all leaves
struct metaVar *metaVar = NULL;
while((metaVar = slPopHead(&(metaObj->vars))) != NULL)
{
if(metaVar->val)
freeMem(metaVar->val);
if(metaVar->var)
freeMem(metaVar->var);
freeMem(metaVar);
}
// The rest of root
if(metaObj->objName)
freeMem(metaObj->objName);
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)
if(rootVar->valHash != NULL)
hashFree(&(rootVar->valHash));
// free all limbs
struct metaLimbVal *limbVal = NULL;
while((limbVal = slPopHead(&(rootVar->vals))) != NULL)
{
// Free hash first (shared memory)
if(limbVal->objHash != NULL)
hashFree(&(limbVal->objHash));
// free all leaves
struct metaLeafObj *leafObj = NULL;
while((leafObj = slPopHead(&(limbVal->objs))) != NULL)
{
if(leafObj->objName != NULL)
freeMem(leafObj->objName);
freeMem(leafObj);
}
// The rest of limb
if(limbVal->val)
freeMem(limbVal->val);
freeMem(limbVal);
}
// The rest of root
if(rootVar->var)
freeMem(rootVar->var);
freeMem(rootVar);
}
freez(metaByVarsPtr);
}
}
// TODO: Print formatted metadata lines!