d51422da1797f4b482f2a122123aed55cb60e0e5
kent
  Fri Apr 19 16:20:53 2013 -0700
Added -addBin option at Angie's request.
diff --git src/hg/autoSql/autoSql.c src/hg/autoSql/autoSql.c
index f4d1225..5a412cf 100644
--- src/hg/autoSql/autoSql.c
+++ src/hg/autoSql/autoSql.c
@@ -8,59 +8,62 @@
  * parses is quirky), but the code generator is u-g-l-y.
  *
  * This file is copyright 2002-2005 Jim Kent, but license is hereby
  * granted for all use - public, private or commercial. */
 
 #include "common.h"
 #include "errabort.h"
 #include "linefile.h"
 #include "obscure.h"
 #include "dystring.h"
 #include "asParse.h"
 #include "options.h"
 
 
 boolean withNull = FALSE;
+boolean addBin = FALSE;
 boolean makeJson = FALSE;
 boolean makeDjango = FALSE;
 boolean defaultZeros = FALSE;
 
 void usage()
 /* Explain usage and exit. */
 {
 errAbort("autoSql - create SQL and C code for permanently storing\n"
          "a structure in database and loading it back into memory\n"
 	 "based on a specification file\n"
 	 "usage:\n"
 	 "    autoSql specFile outRoot {optional: -dbLink -withNull -json} \n"
 	 "This will create outRoot.sql outRoot.c and outRoot.h based\n"
 	 "on the contents of specFile. \n"
          "\n"
          "options:\n"
          "  -dbLink - optionally generates code to execute queries and\n"
          "            updates of the table.\n"
+	 "  -addBin - Add an initial bin field and index it as (chrom,bin)\n"
 	 "  -withNull - optionally generates code and .sql to enable\n"
          "              applications to accept and load data into objects\n"
 	 "              with potential 'missing data' (NULL in SQL)\n"
          "              situations.\n"
 	 "  -defaultZeros - will put zero and or empty string as default value\n"
          "  -django - generate method to output object as django model Python code\n"
 	 "  -json - generate method to output the object in JSON (JavaScript) format.\n");
 }
 
 static struct optionSpec optionSpecs[] = {
     {"dbLink", OPTION_BOOLEAN},
+    {"addBin", OPTION_BOOLEAN},
     {"withNull", OPTION_BOOLEAN},
     {"defaultZeros", OPTION_BOOLEAN},
     {"json", OPTION_BOOLEAN},
     {"django", OPTION_BOOLEAN},
     {NULL, 0}
 };
 
 void sqlColumn(struct asColumn *col, FILE *f)
 /* Print out column in SQL. */
 {
 fprintf(f, "    %s ", col->name);
 struct dyString *type = asColumnToSqlType(col);
 fprintf(f, "%s", type->string);
 if (col->autoIncrement)
     {
@@ -123,35 +126,43 @@
 	    errAbort("Unrecognized index type %s", type);
 	if (!gotIndex)
 	    {
 	    gotIndex = TRUE;
 	    }
 	else
 	    {
 	    fprintf(f, ",\n");
 	    }
 	fprintf(f, "    %s(%s", sqlType, col->name);
 	if (index->size != 0)
 	    fprintf(f, "(%d)", index->size);
 	fprintf(f, ")");
 	}
     }
+if (addBin && asColumnFind(table, "chrom") != NULL && asColumnFind(table, "bin") != NULL)
+    {
+    if (gotIndex)
+	fprintf(f, ",\n");
+    fprintf(f, "    INDEX (chrom,bin)");
+    gotIndex = TRUE;
+    }
 
 if (!gotIndex)
     fprintf(f, "    PRIMARY KEY(%s)\n", table->columnList->name);
 else
     fprintf(f, "\n");
+
 fprintf(f, ");\n");
 }
 
 void djangoEnumChoices(struct asColumn *col, FILE *f)
 /* Write out a list of choices to use with a django enum. */
 {
 fprintf(f, "    %sChoices = (\n", col->name);
 struct slName *val;
 for (val = col->values; val != NULL; val = val->next)
     fprintf(f, "        ('%s', '%s'),\n", val->name, val->name);
 fprintf(f, "    )\n");
 }
 
 int longestValue(struct asColumn *col)
 /* Return length of longest value in col->values list */
@@ -1895,57 +1906,81 @@
     {
     if (internalsNeedFree(obj))
 	makeFreeInternals(obj, cFile, hFile);
     }
 else
     {
     makeFree(obj, cFile, hFile);
     makeFreeList(obj, cFile, hFile);
     }
 makeOutput(obj, cFile, hFile);
 if (makeJson)
     makeJsonOutput(obj, cFile, hFile);
 verbose(2, "Made %s object\n", obj->name);
 }
 
+void addBinToChromTables(struct asObject *asList)
+/* Add bin as first field to tables with a chrom field. */
+{
+int addCount = 0;   /* Count how many additions we make */
+struct asObject *as;
+for (as = asList; as != NULL; as = as->next)
+    {
+    if (asColumnFind(as, "chrom") && !asColumnFind(as, "bin"))
+        {
+	++addCount;
+	struct asColumn *col;
+	AllocVar(col);
+	col->name = cloneString("bin");
+	col->comment = cloneString("Bin number for browser speedup");
+	col->lowType = asTypeFindLow("uint");
+	slAddHead(&as->columnList, col);
+	}
+    }
+if (addCount == 0)
+    errAbort("No chrom fields, which are needed for -addBin option");
+}
 
 int main(int argc, char *argv[])
 {
 struct asObject *objList, *obj;
 char *outRoot, outTail[256];
 char dotC[256];
 char dotH[256];
 char dotSql[256];
 char dotDjango[256];
 FILE *cFile;
 FILE *hFile;
 FILE *sqlFile;
 FILE *djangoFile = NULL;
 char defineName[256];
 boolean doDbLoadAndSave = FALSE;
 
 optionInit(&argc, argv, optionSpecs);
 doDbLoadAndSave = optionExists("dbLink");
+addBin = optionExists("addBin");
 withNull = optionExists("withNull");
 defaultZeros = optionExists("defaultZeros");
 makeJson = optionExists("json");
 makeDjango = optionExists("django");
 
 if (argc != 3)
     usage();
 
 objList = asParseFile(argv[1]);
+if (addBin)
+    addBinToChromTables(objList);
 outRoot = argv[2];
 /* don't embed directories in files */
 splitPath(outRoot, NULL, outTail, NULL);
 
 safef(dotC, sizeof(dotC), "%s.c", outRoot);
 cFile = mustOpen(dotC, "w");
 safef(dotH, sizeof(dotH), "%s.h", outRoot);
 hFile = mustOpen(dotH, "w");
 safef(dotSql, sizeof(dotSql), "%s.sql", outRoot);
 sqlFile = mustOpen(dotSql, "w");
 if (makeDjango)
     {
     safef(dotDjango, sizeof(dotDjango), "%s.django", outRoot);
     djangoFile = mustOpen(dotDjango, "w");
     }