static struct joinerPair *joinerPairClone(struct joinerPair *jp) /* Return duplicate (deep copy) of joinerPair. */ { struct joinerPair *dupe; AllocVar(dupe); dupe->a = joinerDtfClone(jp->a); dupe->b = joinerDtfClone(jp->b); dupe->identifier = jp->identifier; return dupe; }
static void addDtfListToBundle(struct hash *hash, struct tableJoiner **pList, struct joinerDtf *dtfList, boolean addField) /* Add table to hash/list if haven't seen it already. Optionally add * field to table. */ { char fullName[256]; struct joinerDtf *dtf, *dupe; struct tableJoiner *tj; for (dtf = dtfList; dtf != NULL; dtf = dtf->next) { safef(fullName, sizeof(fullName), "%s.%s", dtf->database, dtf->table); tj = hashFindVal(hash, fullName); if (tj == NULL) { AllocVar(tj); hashAdd(hash, fullName, tj); tj->database = dtf->database; tj->table = dtf->table; slAddHead(pList, tj); } if (addField) { dupe = joinerDtfClone(dtf); slAddTail(&tj->fieldList, dupe); } } }
void tjLoadSome(struct region *regionList, struct joinedTables *joined, int fieldOffset, int keyOffset, char *idField, struct hash *idHash, struct slName *chopBefore, struct slName *chopAfter, struct tableJoiner *tj, boolean isPositional, boolean isFirst) /* Load up rows. */ { struct region *region; struct dyString *sqlFields = dyStringNew(0); struct joinerDtf *dtf; struct slRef *ref; struct joinerPair *jp; int fieldCount = 0, keyCount = 0; int idFieldIx = -1; struct sqlConnection *conn = hAllocConn(tj->database); char *identifierFilter = NULL; char *filter; boolean needUpdateFilter = FALSE; struct joinedRow *jr; if (isFirst) identifierFilter = identifierWhereClause(idField, idHash); filter = filterClause(tj->database, tj->table, regionList->chrom, identifierFilter); /* Record combined filter. */ // Show only the SQL filter built from filter page options, not identifierFilter, // because identifierFilter can get enormous (like 126kB for 12,500 rsIDs). char *filterNoIds = filterClause(tj->database, tj->table, regionList->chrom, NULL); if (filterNoIds != NULL) { if (joined->filter == NULL) joined->filter = dyStringNew(0); else dyStringAppend(joined->filter, " AND "); dyStringAppend(joined->filter, filterNoIds); if (!isFirst) { needUpdateFilter = TRUE; for (jr = joined->rowList; jr != NULL; jr = jr->next) jr->hitThisTable = FALSE; } } /* Create field spec for sql - first fields user will see, and * second keys if any. */ for (dtf = tj->fieldList; dtf != NULL; dtf = dtf->next) { struct joinerDtf *dupe = joinerDtfClone(dtf); slAddTail(&joined->fieldList, dupe); dyStringAddList(sqlFields, dtf->field); ++fieldCount; } for (ref = tj->keysOut; ref != NULL; ref = ref->next) { struct joinerDtf *dupe; jp = ref->val; dupe = joinerDtfClone(jp->a); slAddTail(&joined->keyList, dupe); dyStringAddList(sqlFields, jp->a->field); ++keyCount; } if (idHash != NULL) { if (idField == NULL) internalErr(); idFieldIx = fieldCount + keyCount; dyStringAddList(sqlFields, idField); } for (region = regionList; region != NULL; region = region->next) { char **row; /* We free at end of loop so we get new one for each chromosome. */ char *filter = filterClause(tj->database, tj->table, region->chrom, identifierFilter); struct sqlResult *sr = regionQuery(conn, tj->table, sqlFields->string, region, isPositional, filter); while (sr != NULL && (row = sqlNextRow(sr)) != NULL) { if (idFieldIx < 0) { if (jrRowAdd(joined, row, fieldCount, keyCount) == NULL) break; } else { char *id = row[idFieldIx]; if (isFirst) { if (hashLookup(idHash, id)) { if (jrRowAdd(joined, row, fieldCount, keyCount) == NULL) break; } } else { struct hashEl *bucket; id = chopKey(chopBefore, chopAfter, id); for (bucket = hashLookup(idHash, id); bucket != NULL; bucket = hashLookupNext(bucket)) { jr = bucket->val; jr->hitThisTable = TRUE; jrRowExpand(joined, jr, row, fieldOffset, fieldCount, keyOffset, keyCount); } } } } sqlFreeResult(&sr); freez(&filter); if (!isPositional) break; } if (isFirst) slReverse(&joined->rowList); if (needUpdateFilter) { for (jr = joined->rowList; jr != NULL; jr = jr->next) { jr->passedFilter &= jr->hitThisTable; } } tj->loaded = TRUE; hFreeConn(&conn); }