src/hg/lib/jksql.c 1.133

1.133 2009/08/28 00:56:22 galt
added useful comments, put in fastest method found to determine if a table exists, added extention function sqlGetRestultsExt to help with testing and generally getting better error info out of mysql
Index: src/hg/lib/jksql.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/lib/jksql.c,v
retrieving revision 1.132
retrieving revision 1.133
diff -b -B -U 4 -r1.132 -r1.133
--- src/hg/lib/jksql.c	25 Aug 2009 00:10:44 -0000	1.132
+++ src/hg/lib/jksql.c	28 Aug 2009 00:56:22 -0000	1.133
@@ -817,10 +817,17 @@
 typedef MYSQL_RES *	STDCALL ResGetter(MYSQL *mysql);
 
 static struct sqlResult *sqlUseOrStore(struct sqlConnection *sc, 
 	char *query, ResGetter *getter, boolean abort)
-/* Returns NULL if result was empty.  Otherwise returns a structure
- * that you can do sqlRow() on. */
+/* Returns NULL if result was empty and getter==mysql_use_result.  
+ * Otherwise returns a structure that you can do sqlRow() on.
+ * Watch out for subtle differences between mysql_store_result and mysql_use_result.
+ * We seem to be only using mysql_use_result these days,
+ * but mysql_store_result has left a big footprint in the code/comments.
+ * In particular, mysql_store_result can return NULL indicating an empty resultset.
+ * But mysql_use_result cannot do that. Instead NULL return means error
+ * and the user must call next_row to see if there's anything in the resultset.
+ */
 {
 assert(!sc->isFree);
 MYSQL *conn = sc->conn;
 struct sqlResult *res = NULL;
@@ -989,12 +996,11 @@
 {
 char query[256];
 struct sqlResult *sr;
 
-safef(query, sizeof(query), "describe %s", table);
+safef(query, sizeof(query), "SELECT 1 FROM %s LIMIT 0", table);
 if ((sr = sqlUseOrStore(sc,query,mysql_use_result, FALSE)) == NULL)
     return FALSE;
-sqlNextRow(sr);	/* Just discard. */
 sqlFreeResult(&sr);
 return TRUE;
 }
 
@@ -1071,41 +1077,52 @@
     *retOk = TRUE;
 return row;
 }
 
-boolean sqlTableOk(struct sqlConnection *sc, char *table)
-/* Return TRUE if a table not only exists, but also is not corrupted. */
-{
-char query[256];
-struct sqlResult *sr;
-boolean ret = TRUE;
-safef(query, sizeof(query), "select * from %s limit 1,1", table);
-if ((sr = sqlUseOrStore(sc, query, mysql_use_result, FALSE)) == NULL)
-    {
-    fprintf(stderr, "ASH: Got nothing from select on %s.%s.  pid=%ld\n",
-	    scConnDb(sc), table, (long)getpid());
-    /* An error here is OK if and only if the table exists and is empty: */
-    return (sqlTableSizeIfExists(sc, table) == 0);
+
+
+struct sqlResult *sqlGetResultExt(struct sqlConnection *sc, char *query, unsigned int *errorNo, char **error)
+/* Returns NULL if it had an error.  
+ * Otherwise returns a structure that you can do sqlRow() on.  
+ * If there was an error, *errorNo will be set to the mysql error number, 
+ * and *error will be set to the mysql error string, which MUST NOT be freed. */
+{
+struct sqlResult *sr = sqlUseOrStore(sc, query, mysql_use_result, FALSE);
+if (sr)
+    {
+    MYSQL *conn = sc->conn;
+    if (errorNo)
+    	*errorNo=mysql_errno(conn);
+    if (error)
+    	*error=(char *)mysql_error(conn);
     }
 else
-    /* Discard row, but see if we get an error while reading it. */
-    sqlMaybeNextRow(sr, &ret);
-sqlFreeResult(&sr);
-if (ret == FALSE)
-    fprintf(stderr, "ASH: Error reading result of select on %s.%s!  pid=%ld\n",
-	    scConnDb(sc), table, (long)getpid());
-return ret;
+    {
+    if (errorNo)
+    	*errorNo=0;
+    if (error)
+    	*error=NULL;
+    }
+return sr;
 }
 
+
 struct sqlResult *sqlGetResult(struct sqlConnection *sc, char *query)
-/* Returns NULL if result was empty.  Otherwise returns a structure
- * that you can do sqlRow() on. */
+/* (Returns NULL if result was empty. : 
+ *     old info, only applies with mysql_store_result not mysql_use_result)  
+ * Otherwise returns a structure that you can do sqlRow() on. */
 {
 return sqlUseOrStore(sc,query,mysql_use_result, TRUE);
 }
 
 struct sqlResult *sqlMustGetResult(struct sqlConnection *sc, char *query)
-/* Query database. If result empty squawk and die. */
+/* Query database. 
+ * old comment: If result empty squawk and die.
+ *    This only applied back when sqlGetResult was using mysql_store_result.
+ * These days, with mysql_use_result, we cannot know ahead of time
+ * if there are results, we can only know by actually trying to fetch a row.
+ * At then how would we put it back?  So in fact right now sqlMustGetResult
+ * is no different than sqlGetResult.  */
 {
 struct sqlResult *res = sqlGetResult(sc,query);
 if (res == NULL)
 	errAbort("Object not found in database.\nQuery was %s", query);