852fd481e68ca3d3feaf29e1da20e1b49304f9ce angie Fri Mar 14 10:03:48 2014 -0700 Fixing problem with hgVai code not recognizing a genePred whoseasObject was derived from sql field info. Unfortunately, when a sql field's type is longblob, we don't know whether its autoSql definition was a list (like exonStarts[exonCount]) or just an lstring. To play it safe, we call it an lstring which works fine for feeding data through the annoGrator system. However, when comparing a sql-derived asObj with lstring to the real autoSql-derived asObj, asCompareObjs will see different types for the same field and return false. So for the purposes of recognizing a genePred, we need to simply compare column names. diff --git src/lib/asParse.c src/lib/asParse.c index 867bd79..4371616 100644 --- src/lib/asParse.c +++ src/lib/asParse.c @@ -77,57 +77,76 @@ struct dyString *type = dyStringNew(32); if ((lt->type == t_enum) || (lt->type == t_set)) sqlSymDef(col, type); else if (col->isList || col->isArray) dyStringPrintf(type, "longblob"); else if (lt->type == t_char) dyStringPrintf(type, "char(%d)", col->fixedSize ? col->fixedSize : 1); else dyStringPrintf(type, "%s", lt->sqlName); return type; } char *asTypeNameFromSqlType(char *sqlType) /* Return the autoSql type name (not enum) for the given SQL type, or NULL. * Don't attempt to free result. */ +// Unfortunately, when sqlType is longblob, we don't know whether it's a list +// of some type or an lstring. :( { if (sqlType == NULL) return NULL; -// We need to strip '(...)' strings from all types except 'varchar' which must be 'varchar(255)' -int len = strlen(sqlType) + 8; -char buf[len]; +// For comparison with asTypes[*], we need to strip '(...)' strings from all types +// except 'varchar' which must be 'varchar(255)'. For 'char', we need to remember +// what was in the '(...)' so we can add back the '[...]' after type comparison. +boolean isArray = FALSE; +int arraySize = 0; +static char buf[1024]; if (startsWith("varchar", sqlType)) - safecpy(buf, len, "varchar(255)"); + safecpy(buf, sizeof(buf), "varchar(255)"); else { - safecpy(buf, len, sqlType); + safecpy(buf, sizeof(buf), sqlType); char *leftParen = strstr(buf, " ("); if (leftParen == NULL) leftParen = strchr(buf, '('); if (leftParen != NULL) { + isArray = startsWith("char", sqlType); char *rightParen = strrchr(leftParen, ')'); if (rightParen != NULL) { + *rightParen = '\0'; + arraySize = atoi(leftParen+1); strcpy(leftParen, rightParen+1); } + else + errAbort("asTypeNameFromSqlType: mismatched ( in sql type def'%s'", sqlType); } } int i; for (i = 0; i < ArraySize(asTypes); i++) if (sameString(buf, asTypes[i].sqlName)) + { + if (isArray) + { + int typeLen = strlen(buf); + safef(buf+typeLen, sizeof(buf)-typeLen, "[%d]", arraySize); + return buf; + } + else return asTypes[i].name; + } return NULL; } static struct asColumn *mustFindColumn(struct asObject *table, char *colName) /* Return column or die. */ { struct asColumn *col; for (col = table->columnList; col != NULL; col = col->next) { if (sameWord(col->name, colName)) return col; } errAbort("Couldn't find column %s", colName); return NULL; @@ -611,15 +630,32 @@ if (!differencesFound && checkCount < numColumnsToCheck) errAbort("Unexpected error in asCompareObjLists: asked to compare %d columns in %s and %s, but only found %d in one or both asObjects." , numColumnsToCheck, name1, name2, checkCount); } if (differencesFound) { if (abortOnDifference) errAbort("asObjects differ."); else verbose(verboseLevel,"asObjects differ. Matching field count=%d\n", checkCount); } if (retNumColumnsSame) *retNumColumnsSame = checkCount; return (!differencesFound); } + +boolean asColumnNamesMatchFirstN(struct asObject *as1, struct asObject *as2, int n) +/* Compare only the column names of as1 and as2, not types because if an asObj has been + * created from sql type info, longblobs are cast to lstrings but in the proper autoSql + * might be lists instead (e.g. longblob in sql, uint exonStarts[exonCount] in autoSql. */ +{ +struct asColumn *col1 = as1->columnList, *col2 = as2->columnList; +int checkCount = 0; +for (col1 = as1->columnList, col2 = as2->columnList; + col1 != NULL && col2 != NULL && checkCount < n; + col1 = col1->next, col2 = col2->next, ++checkCount) + { + if (!sameOk(col1->name, col2->name)) + return FALSE; + } +return TRUE; +}