Example #1
0
File: joiner.c Project: bowhan/kent
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);
}