struct slName *cartTrackDbTablesForTrack(char *db, struct trackDb *track, boolean useJoiner) /* Return list of all tables associated with track. If useJoiner, the result can include * non-positional tables that are related to track by all.joiner. */ { static struct joiner *allJoiner = NULL; struct hash *uniqHash = newHash(8); struct slName *name, *nameList = NULL; char *trackTable = track->table; hashAdd(uniqHash, trackTable, NULL); if (useJoiner) { if (allJoiner == NULL) allJoiner = joinerRead("all.joiner"); struct joinerPair *jpList, *jp; jpList = joinerRelate(allJoiner, db, trackTable); for (jp = jpList; jp != NULL; jp = jp->next) { struct joinerDtf *dtf = jp->b; if (cartTrackDbIsAccessDenied(dtf->database, dtf->table)) continue; char buf[256]; char *s; if (sameString(dtf->database, db)) s = dtf->table; else { safef(buf, sizeof(buf), "%s.%s", dtf->database, dtf->table); s = buf; } if (!hashLookup(uniqHash, s)) { hashAdd(uniqHash, s, NULL); name = slNameNew(s); slAddHead(&nameList, name); } } slNameSort(&nameList); } /* suppress for parent tracks -- only the subtracks have tables */ if (track->subtracks == NULL) { name = slNameNew(trackTable); slAddHead(&nameList, name); } addTablesAccordingToTrackType(db, &nameList, uniqHash, track); hashFree(&uniqHash); return nameList; }
static struct joinerPair *rFindRoute(struct joiner *joiner, struct joinerDtf *a, struct joinerDtf *b, int level, int maxLevel) /* Find a path that connects the two fields if possible. Do limited * recursion. */ { struct joinerPair *jpList, *jp; struct joinerPair *path = NULL; jpList = joinerRelate(joiner, a->database, a->table); for (jp = jpList; jp != NULL; jp = jp->next) { if (joinerDtfSameTable(jp->b, b)) { path = joinerPairClone(jp); break; } } if (path == NULL && level < maxLevel) { for (jp = jpList; jp != NULL; jp = jp->next) { identifierStack[level] = jp->identifier; if (!identifierInArray(jp->identifier, identifierStack, level)) { identifierStack[level] = jp->identifier; path = rFindRoute(joiner, jp->b, b, level+1, maxLevel); if (path != NULL) { struct joinerPair *jpClone = joinerPairClone(jp); slAddHead(&path, jpClone); break; } } } } joinerPairFreeList(&jpList); return path; }
static void showLinkedTables(struct joiner *joiner, struct dbTable *inList, char *varPrefix, char *buttonName, char *buttonText) /* Print section with list of linked tables and check boxes to turn them * on. */ { struct dbTable *outList = NULL, *out, *in; char dtName[256]; struct hash *uniqHash = newHash(0); struct hash *inHash = newHash(8); /* Build up list of tables we link to in outList. */ for (in = inList; in != NULL; in = in->next) { struct sqlConnection *conn = NULL; if (!trackHubDatabase(database)) conn = hAllocConn(in->db); struct joinerPair *jpList, *jp; /* Keep track of tables in inList. */ safef(dtName, sizeof(dtName), "%s.%s", inList->db, inList->table); hashAdd(inHash, dtName, NULL); /* First table in input is not allowed in output. */ if (in == inList) hashAdd(uniqHash, dtName, NULL); /* Scan through joining information and add tables, * avoiding duplicate additions. */ jpList = joinerRelate(joiner, in->db, in->table); for (jp = jpList; jp != NULL; jp = jp->next) { safef(dtName, sizeof(dtName), "%s.%s", jp->b->database, jp->b->table); if (!hashLookup(uniqHash, dtName) && !cartTrackDbIsAccessDenied(jp->b->database, jp->b->table)) { hashAdd(uniqHash, dtName, NULL); out = dbTableNew(jp->b->database, jp->b->table); slAddHead(&outList, out); } } joinerPairFreeList(&jpList); hFreeConn(&conn); } slSort(&outList, dbTableCmp); /* Print html. */ if (outList != NULL) { webNewSection("Linked Tables"); hTableStart(); for (out = outList; out != NULL; out = out->next) { struct sqlConnection *conn = hAllocConn(out->db); struct asObject *asObj = asForTable(conn, out->table); char *var = dbTableVar(varPrefix, out->db, out->table); hPrintf("<TR>"); hPrintf("<TD>"); cgiMakeCheckBox(var, varOn(var)); hPrintf("</TD>"); hPrintf("<TD>%s</TD>", out->db); hPrintf("<TD>%s</TD>", out->table); hPrintf("<TD>"); if (asObj != NULL) hPrintf("%s", asObj->comment); else hPrintf(" "); hPrintf("</TD>"); hPrintf("</TR>"); hFreeConn(&conn); } hTableEnd(); hPrintf("<BR>"); cgiMakeButton(buttonName, buttonText); } }