fdc83280a6a19270e464640b4219d9ade2f6333b
galt
  Thu Mar 22 13:45:45 2012 -0700
workaround for mysql5.0 bug in warnings reported during load data infile
diff --git src/hg/lib/jksql.c src/hg/lib/jksql.c
index 59fcada..784c52f 100644
--- src/hg/lib/jksql.c
+++ src/hg/lib/jksql.c
@@ -1221,76 +1221,69 @@
 /* Rows matched: 40 Changed: 40 Warnings: 0 */
 monitorEnter();
 info = mysql_info(conn->conn);
 monitorLeave();
 if (info != NULL)
     numScan = sscanf(info, "Rows matched: %d Changed: %d Warnings: %*d",
                      &numMatched, &numChanged);
 if ((info == NULL) || (numScan < 2))
     errAbort("can't get info (maybe not an sql UPDATE): %s", query);
 sqlFreeResult(&sr);
 if (matched != NULL)
     *matched = numMatched;
 return numChanged;
 }
 
-static boolean isMySql4(struct sqlConnection *conn)
-/* determine if this is at least mysql 4.0 or newer */
-{
-char majorVerBuf[64];
-char *dotPtr = strchr(conn->conn->server_version, '.');
-int len = (dotPtr - conn->conn->server_version);
-assert(dotPtr != NULL);
-strncpy(majorVerBuf, conn->conn->server_version, len);
-majorVerBuf[len] = '\0';
-
-return (sqlUnsigned(majorVerBuf) >= 4);
-}
-
 void sqlWarnings(struct sqlConnection *conn, int numberOfWarnings)
 /* Show the number of warnings requested. New feature in mysql5. */
 {
 struct sqlResult *sr;
 char **row;
 char query[256];
 struct dyString *dy = dyStringNew(0);
 safef(query,sizeof(query),"show warnings limit 0, %d", numberOfWarnings);
 sr = sqlGetResult(conn, query);
 dyStringPrintf(dy, "Level Code Message\n");
 while ((row = sqlNextRow(sr)) != NULL)
     {
     dyStringPrintf(dy, "%s %s %s\n", row[0], row[1], row[2]);
     }
 sqlFreeResult(&sr);
 warn("%s", dy->string);
 dyStringFree(&dy);
 }
 
+int sqlWarnCount(struct sqlConnection *conn)
+/* Return the number of warnings. New feature in mysql5. */
+{
+return sqlQuickNum(conn, "SHOW COUNT(*) WARNINGS");
+}
+
+
 void sqlLoadTabFile(struct sqlConnection *conn, char *path, char *table,
                     unsigned options)
 /* Load a tab-seperated file into a database table, checking for errors.
  * Options are the SQL_TAB_* bit set. SQL_TAB_FILE_ON_SERVER is ignored if
  * sqlIsRemote() returns true. */
 {
 assert(!conn->isFree);
 char tabPath[PATH_LEN];
 char query[PATH_LEN+256];
 int numScan, numRecs, numSkipped, numWarnings;
 char *localOpt, *concurrentOpt, *dupOpt;
 const char *info;
 struct sqlResult *sr;
-boolean mysql4 = isMySql4(conn);
 
 /* Doing an "alter table disable keys" command implicitly commits the current
    transaction. Don't want to use that optimization if we need to be transaction
    safe. */
 /* FIXME: markd 2003/01/05: mysql 4.0.17 - the alter table enable keys hangs,
  * disable this optimization for now. Verify performance on small loads
  * before re-enabling*/
 # if 0
 boolean doDisableKeys = !(options & SQL_TAB_TRANSACTION_SAFE);
 #else
 boolean doDisableKeys = FALSE;
 #endif
 
 /* determine if tab file can be accessed directly by the database, or send
  * over the network */
@@ -1307,80 +1300,86 @@
     strcat(tabPath, path);
     localOpt = "";
     }
 else
     {
     strcpy(tabPath, path);
     localOpt = "LOCAL";
     }
 
 /* optimize for concurrent to others to access the table. */
 if (options & SQL_TAB_FILE_CONCURRENT)
     concurrentOpt = "CONCURRENT";
 else
     {
     concurrentOpt = "";
-    if (mysql4 && doDisableKeys)
+    if (doDisableKeys)
         {
         /* disable update of indexes during load. Inompatible with concurrent,
          * since enable keys locks other's out. */
         safef(query, sizeof(query), "ALTER TABLE %s DISABLE KEYS", table);
         sqlUpdate(conn, query);
         }
     }
 
 if (options & SQL_TAB_REPLACE)
     dupOpt = "REPLACE";
 else
     dupOpt = "";
 
 safef(query, sizeof(query),  "LOAD DATA %s %s INFILE '%s' %s INTO TABLE %s",
       concurrentOpt, localOpt, tabPath, dupOpt, table);
 sr = sqlGetResult(conn, query);
 monitorEnter();
 info = mysql_info(conn->conn);
 monitorLeave();
+
 if (info == NULL)
     errAbort("no info available for result of sql query: %s", query);
 numScan = sscanf(info, "Records: %d Deleted: %*d  Skipped: %d  Warnings: %d",
                  &numRecs, &numSkipped, &numWarnings);
 if (numScan != 3)
     errAbort("can't parse sql load info: %s", info);
 sqlFreeResult(&sr);
 
+/* mysql 5.0 bug: mysql_info returns unreliable warnings count, so use this instead: */
+numWarnings = sqlWarnCount(conn);
+
 if ((numSkipped > 0) || (numWarnings > 0))
     {
     boolean doAbort = TRUE;
     if ((numSkipped > 0) && (options & SQL_TAB_FILE_WARN_ON_ERROR))
         doAbort = FALSE;  /* don't abort on errors */
     else if ((numWarnings > 0) &&
              (options & (SQL_TAB_FILE_WARN_ON_ERROR|SQL_TAB_FILE_WARN_ON_WARN)))
         doAbort = FALSE;  /* don't abort on warnings */
     if (numWarnings > 0)
 	{
 	sqlWarnings(conn, 10);  /* show the first 10 warnings */
 	}
     if (doAbort)
         errAbort("load of %s did not go as planned: %d record(s), "
                  "%d row(s) skipped, %d warning(s) loading %s",
                  table, numRecs, numSkipped, numWarnings, path);
     else
         warn("Warning: load of %s did not go as planned: %d record(s), "
              "%d row(s) skipped, %d warning(s) loading %s",
              table, numRecs, numSkipped, numWarnings, path);
     }
-if (((options & SQL_TAB_FILE_CONCURRENT) == 0) && mysql4 && doDisableKeys)
+
+
+if (((options & SQL_TAB_FILE_CONCURRENT) == 0) && doDisableKeys)
     {
     /* reenable update of indexes */
     safef(query, sizeof(query), "ALTER TABLE %s ENABLE KEYS", table);
     sqlUpdate(conn, query);
     }
 }
 
 boolean sqlExists(struct sqlConnection *conn, char *query)
 /* Query database and return TRUE if it had a non-empty result. */
 {
 struct sqlResult *sr;
 if ((sr = sqlGetResult(conn,query)) == NULL)
     return FALSE;
 else
     {