eb712bae538ade6333382032594720b0a55f971d angie Wed Mar 28 08:22:35 2012 -0700 Feature #6152 (Variant Annotation Tool): instead of having a callercreate the sql connection outside of annoStreamDb, and have to remember not to share it, just allocate the connection inside annoStreamDb. This introduces a dependency on hdb, but I guess that's inevitable. :) diff --git src/hg/lib/annoStreamDb.c src/hg/lib/annoStreamDb.c index 7d80562..f0fa554 100644 --- src/hg/lib/annoStreamDb.c +++ src/hg/lib/annoStreamDb.c @@ -11,32 +11,31 @@ // Private members struct sqlConnection *conn; // Database connection (e.g. hg19 or customTrash) char *table; // Table name, must exist in database struct sqlResult *sr; // SQL query result from which we grab rows boolean hasBin; // 1 if SQL table's first column is bin boolean omitBin; // 1 if table hasBin and autoSql doesn't have bin int numCols; // Number of columns in autoSql char *chromField; // Name of chrom-ish column in table char *startField; // Name of chromStart-ish column in table char *endField; // Name of chromEnd-ish column in table int chromIx; // Index of chrom-ish col in autoSql or bin-less table int startIx; // Index of chromStart-ish col in autoSql or bin-less table int endIx; // Index of chromEnd-ish col in autoSql or bin-less table }; -static void asdSetRegionDb(struct annoStreamer *vSelf, - char *chrom, uint regionStart, uint regionEnd) +static void asdSetRegion(struct annoStreamer *vSelf, char *chrom, uint regionStart, uint regionEnd) /* Set region -- and free current sqlResult if there is one. */ { annoStreamerSetRegion(vSelf, chrom, regionStart, regionEnd); struct annoStreamDb *self = (struct annoStreamDb *)vSelf; if (self->sr != NULL) sqlFreeResult(&(self->sr)); } static void asdDoQuery(struct annoStreamDb *self) /* Return a sqlResult for a query on table items in position range. */ // NOTE: it would be possible to implement filters at this level, as in hgTables. { struct annoStreamer *streamer = &(self->streamer); struct dyString *query = dyStringCreate("select * from %s", self->table); if (!streamer->positionIsGenome) @@ -57,68 +56,69 @@ dyStringFree(&query); self->sr = sr; } static char **nextRowUnfiltered(struct annoStreamDb *self) /* Fetch the next row from the sqlResult, and skip past table's bin field if necessary. */ { char **row = sqlNextRow(self->sr); if (row == NULL) return NULL; // Skip table's bin field if not in autoSql: row += self->omitBin; return row; } -static struct annoRow *asdNextRowDb(struct annoStreamer *vSelf) +static struct annoRow *asdNextRow(struct annoStreamer *vSelf) /* Perform sql query if we haven't already and return a single * annoRow, or NULL if there are no more items. */ { struct annoStreamDb *self = (struct annoStreamDb *)vSelf; if (self->sr == NULL) asdDoQuery(self); if (self->sr == NULL) // This is necessary only if we're using sqlStoreResult in asdDoQuery, harmless otherwise: return NULL; char **row = nextRowUnfiltered(self); if (row == NULL) return NULL; // Skip past any left-join failures until we get a right-join failure, a passing row, or EOF. boolean rightFail = FALSE; while (annoFilterRowFails(vSelf->filters, row, self->numCols, &rightFail)) { if (rightFail) break; row = nextRowUnfiltered(self); if (row == NULL) return NULL; } char *chrom = row[self->omitBin+self->chromIx]; uint chromStart = sqlUnsigned(row[self->omitBin+self->startIx]); uint chromEnd = sqlUnsigned(row[self->omitBin+self->endIx]); return annoRowFromStringArray(chrom, chromStart, chromEnd, rightFail, row, self->numCols); } -static void asdCloseDb(struct annoStreamer **pVSelf) +static void asdClose(struct annoStreamer **pVSelf) /* Close db connection and free self. */ { if (pVSelf == NULL) return; struct annoStreamDb *self = *(struct annoStreamDb **)pVSelf; // Let the caller close conn; it might be from a cache. freeMem(self->table); sqlFreeResult(&(self->sr)); +hFreeConn(&(self->conn)); annoStreamerFree(pVSelf); } static int asColumnFindIx(struct asColumn *list, char *string) /* Return index of first element of asColumn list that matches string. * Return -1 if not found. */ { struct asColumn *ac; int ix = 0; for (ac = list; ac != NULL; ac = ac->next, ix++) if (sameString(string, ac->name)) return ix; return -1; } @@ -146,42 +146,41 @@ static boolean asdInitBed3Fields(struct annoStreamDb *self) /* Use autoSql to figure out which table fields correspond to {chrom, chromStart, chromEnd}. */ { if (asHasFields(self, "chrom", "chromStart", "chromEnd")) return TRUE; if (asHasFields(self, "chrom", "txStart", "txEnd")) return TRUE; if (asHasFields(self, "tName", "tStart", "tEnd")) return TRUE; if (asHasFields(self, "genoName", "genoStart", "genoEnd")) return TRUE; return FALSE; } -struct annoStreamer *annoStreamDbNew(struct sqlConnection *conn, char *table, - struct asObject *asObj) -/* Create an annoStreamer (subclass) object from a database table described by asObj. - * conn must not be shared. */ +struct annoStreamer *annoStreamDbNew(char *db, char *table, struct asObject *asObj) +/* Create an annoStreamer (subclass) object from a database table described by asObj. */ { +struct sqlConnection *conn = hAllocConn(db); if (!sqlTableExists(conn, table)) - errAbort("annoStreamNewDb: table %s doesn't exist", table); + errAbort("annoStreamDbNew: table '%s' doesn't exist in database '%s'", table, db); struct annoStreamDb *self = NULL; AllocVar(self); struct annoStreamer *streamer = &(self->streamer); annoStreamerInit(streamer, asObj); -streamer->setRegion = asdSetRegionDb; -streamer->nextRow = asdNextRowDb; -streamer->close = asdCloseDb; +streamer->setRegion = asdSetRegion; +streamer->nextRow = asdNextRow; +streamer->close = asdClose; self->conn = conn; self->table = cloneString(table); char *asFirstColumnName = streamer->asObj->columnList->name; if (sqlFieldIndex(self->conn, self->table, "bin") == 0) self->hasBin = 1; if (self->hasBin && !sameString(asFirstColumnName, "bin")) self->omitBin = 1; self->numCols = slCount(streamer->asObj->columnList); if (!asdInitBed3Fields(self)) errAbort("annoStreamDbNew: can't figure out which fields of %s to use as " "{chrom, chromStart, chromEnd}.", table); return (struct annoStreamer *)self; }