05094dabf3d005ab35a998ff225443fc4255611f
galt
  Mon Feb 4 23:07:42 2019 -0800
Adding ability to backup and restore the cart and its custom tracks in hgSession.

diff --git src/hg/lib/jksql.c src/hg/lib/jksql.c
index dace78f..e459903 100644
--- src/hg/lib/jksql.c
+++ src/hg/lib/jksql.c
@@ -1650,30 +1650,49 @@
 struct slName *tableList =  sqlListTables(sc);
 sqlHardLockTables(sc, tableList, isWrite);
 slFreeList(&tableList);
 }
 
 boolean sqlMaybeMakeTable(struct sqlConnection *sc, char *table, char *query)
 /* Create table from query if it doesn't exist already.
  * Returns FALSE if didn't make table. */
 {
 if (sqlTableExists(sc, table))
     return FALSE;
 sqlUpdate(sc, query);
 return TRUE;
 }
 
+char *sqlGetCreateTable(struct sqlConnection *sc, char *table)
+/* Get the Create table statement. table must exist. */
+{
+char query[256];
+struct sqlResult *res;
+char **row = NULL;
+char *statement = NULL;
+
+sqlSafef(query, sizeof(query), "show create table %s", table);
+res = sqlGetResult(sc, query);
+if ((row=sqlNextRow(res)))
+    {
+    // skip first column which has useless table name in it.
+    statement = cloneString(row[1]);
+    }
+sqlFreeResult(&res);
+return statement;
+}
+
 void sqlRemakeTable(struct sqlConnection *sc, char *table, char *create)
 /* Drop table if it exists, and recreate it. */
 {
 sqlDropTable(sc, table);
 sqlUpdate(sc, create);
 }
 
 boolean sqlDatabaseExists(char *database)
 /* Return TRUE if database exists. */
 {
 struct sqlConnection *conn = sqlMayConnect(database);
 boolean exists = (conn != NULL);
 sqlDisconnect(&conn);
 return exists;
 }
@@ -2175,40 +2194,30 @@
     MYSQL_FIELD *field = mysql_fetch_field_direct(sr->result, i);
     if (sameString(field->name, colName))
         return i;
     }
 return -1;
 }
 
 int sqlCountColumns(struct sqlResult *sr)
 /* Count the number of columns in result. */
 {
 if(sr != NULL)
     return mysql_field_count(sr->conn->conn);
 return 0;
 }
 
-#ifdef SOMETIMES  /* Not available for all MYSQL environments. */
-int sqlFieldCount(struct sqlResult *sr)
-/* Return number of fields in a row of result. */
-{
-if (sr == NULL)
-    return 0;
-return mysql_field_count(sr->result);
-}
-#endif /* SOMETIMES */
-
 int sqlFieldCount(struct sqlResult *sr)
 /* Return number of fields in a row of result. */
 {
 if (sr == NULL)
     return 0;
 return mysql_num_fields(sr->result);
 }
 
 int sqlCountColumnsInTable(struct sqlConnection *sc, char *table)
 /* Return the number of columns in a table */
 {
 struct sqlResult *sr;
 char **row;
 int count;
 
@@ -3104,30 +3113,73 @@
 ret = cloneString(row[updateIx]);
 sqlFreeResult(&sr);
 return ret;
 }
 
 time_t sqlTableUpdateTime(struct sqlConnection *conn, char *table)
 /* Get last update time for table.
  * Note: does NOT work on innoDB! */
 {
 char *date = sqlTableUpdate(conn, table);
 time_t time = sqlDateToUnixTime(date);
 freeMem(date);
 return time;
 }
 
+static char *sqlTablePropertyFromSchema(struct sqlConnection *conn, char *db, char *table, char *field)
+/* Get table property. Table must exist or will abort. */
+{
+char query[512], **row;
+struct sqlResult *sr;
+char *ret;
+sqlSafef(query, sizeof(query), 
+    "SELECT %s FROM information_schema.TABLES"
+    " WHERE TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s'", field, db, table);
+// the failover strategy for failoverConn does not work for this command, 
+// as it never returns an error. So we run this on the failover server
+// if we have a failover connection and the table is not on the main server
+if (conn->failoverConn && !sqlTableExistsOnMain(conn, table))
+    {
+    sqlConnectIfUnconnected(conn->failoverConn, TRUE);
+    monitorPrintInfo(conn->failoverConn, "SQL_TABLE_STATUS_FAILOVER");
+    sr = sqlGetResult(conn->failoverConn, query);
+    }
+else
+    sr = sqlGetResult(conn, query);
+row = sqlNextRow(sr);
+if (row == NULL)
+    errAbort("Database table %s or field %s doesn't exist", table, field);
+ret = cloneString(row[0]);
+sqlFreeResult(&sr);
+return ret;
+}
+
+unsigned long sqlTableDataSizeFromSchema(struct sqlConnection *conn, char *db, char *table)
+/* Get table data size. Table must exist or will abort. */
+{
+char *sizeString = sqlTablePropertyFromSchema(conn, db, table, "data_length");
+return sqlUnsignedLong(sizeString);
+}
+
+unsigned long sqlTableIndexSizeFromSchema(struct sqlConnection *conn, char *db, char *table)
+/* Get table index size. Table must exist or will abort. */
+{
+char *sizeString = sqlTablePropertyFromSchema(conn, db, table, "index_length");
+return sqlUnsignedLong(sizeString);
+}
+
+
 char *sqlGetPrimaryKey(struct sqlConnection *conn, char *table)
 /* Get primary key if any for table, return NULL if none. */
 {
 struct sqlResult *sr;
 char **row;
 char *key = NULL;
 sr = sqlDescribe(conn, table);
 while ((row = sqlNextRow(sr)) != NULL)
     {
     if (sameWord(row[3], "PRI"))
 	{
         key = cloneString(row[0]);
 	break;
 	}
     }