4cffc3eb6f43e109452b5b52d1f760cf1ea6a981
jcasper
  Sun Jun 7 21:47:37 2026 -0700
Adjusting sessionDb and userDb IDs to be 64-bit in the code, since the database
is now ready for it and we're crossing the threshold.  refs #33554

diff --git src/lib/sqlList.c src/lib/sqlList.c
index 9a0460ae638..dc18d7219af 100644
--- src/lib/sqlList.c
+++ src/lib/sqlList.c
@@ -1,1293 +1,1305 @@
 /* Stuff for processing comma separated lists - a little long so
  * in a separate module from jksql.c though interface is still
  * in jksql.c. 
  *
  * This file is copyright 2002 Jim Kent, but license is hereby
  * granted for all use - public, private or commercial. */
 
 /* The various static routines sql<Type>StaticArray are NOT thread-safe. */
 
 #include "common.h"
 #include "sqlNum.h"
 #include "sqlList.h"
 #include "dystring.h"
 #include "hash.h"
 
 
 int sqlByteArray(char *s, signed char *array, int arraySize)
 /* Convert comma separated list of numbers to an array.  Pass in 
  * array an max size of array. */
 {
 unsigned count = 0;
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0 || count == arraySize)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     array[count++] = sqlSigned(s);
     s = e;
     }
 return count;
 }
 
 void sqlByteStaticArray(char *s, signed char **retArray, int *retSize)
 /* Convert comma separated list of numbers to an array which will be
  * overwritten next call to this function, but need not be freed. */
 {
 static signed char *array = NULL;
 static unsigned alloc = 0;
 unsigned count = 0;
 
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     if (count >= alloc)
 	{
 	if (alloc == 0)
 	    alloc = 64;
 	else
 	    alloc <<= 1;
 	ExpandArray(array, count, alloc);
 	}
     array[count++] = sqlSigned(s);
     s = e;
     }
 *retSize = count;
 *retArray = array;
 }
 
 void sqlByteDynamicArray(char *s, signed char **retArray, int *retSize)
 /* Convert comma separated list of numbers to an dynamically allocated
  * array, which should be freeMem()'d when done. Thread-safe. */
 {
 signed char *array = NULL;
 int count = 0;
 
 if (s)
     {
     count = countSeparatedItems(s, ',');
     if (count > 0)
 	{
 	AllocArray(array, count);
 	count = 0;
 	for (;;)
 	    {
 	    array[count++] = sqlSignedInList(&s);
 	    if (*s++ == 0)
 		break;
 	    if (*s == 0)
 		break;
 	    }
 	}
     }
 *retArray = array;
 *retSize = count;
 }
 
 /*-------------------------*/
 
 int sqlUbyteArray(char *s, unsigned char *array, int arraySize)
 /* Convert comma separated list of numbers to an array.  Pass in 
  * array an max size of array. */
 {
 unsigned count = 0;
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0 || count == arraySize)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     array[count++] = sqlUnsigned(s);
     s = e;
     }
 return count;
 }
 
 void sqlUbyteStaticArray(char *s, unsigned char **retArray, int *retSize)
 /* Convert comma separated list of numbers to an array which will be
  * overwritten next call to this function, but need not be freed. */
 {
 static unsigned char *array = NULL;
 static unsigned alloc = 0;
 unsigned count = 0;
 
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     if (count >= alloc)
 	{
 	if (alloc == 0)
 	    alloc = 64;
 	else
 	    alloc <<= 1;
 	ExpandArray(array, count, alloc);
 	}
     array[count++] = sqlUnsigned(s);
     s = e;
     }
 *retSize = count;
 *retArray = array;
 }
 
 void sqlUbyteDynamicArray(char *s, unsigned char **retArray, int *retSize)
 /* Convert comma separated list of numbers to an dynamically allocated
  * array, which should be freeMem()'d when done. Thread-safe. */
 {
 unsigned char *array = NULL;
 int count = 0;
 
 if (s)
     {
     count = countSeparatedItems(s, ',');
     if (count > 0)
 	{
 	AllocArray(array, count);
 	count = 0;
 	for (;;)
 	    {
 	    array[count++] = sqlUnsignedInList(&s);
 	    if (*s++ == 0)
 		break;
 	    if (*s == 0)
 		break;
 	    }
 	}
     }
 *retArray = array;
 *retSize = count;
 }
 
 /*-------------------------*/
 
 int sqlCharArray(char *s, char *array, int arraySize)
 /* Convert comma separated list of chars to an array.  Pass in 
  * array and max size of array. */
 {
 unsigned count = 0;
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0 || count == arraySize)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     array[count++] = s[0];
     s = e;
     }
 return count;
 }
 
 void sqlCharStaticArray(char *s, char **retArray, int *retSize)
 /* Convert comma separated list of chars to an array which will be
  * overwritten next call to this function, but need not be freed. */
 {
 static char *array = NULL;
 static unsigned alloc = 0;
 unsigned count = 0;
 
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     if (count >= alloc)
 	{
 	if (alloc == 0)
 	    alloc = 64;
 	else
 	    alloc <<= 1;
 	ExpandArray(array, count, alloc);
 	}
     array[count++] = s[0];
     s = e;
     }
 *retSize = count;
 *retArray = array;
 }
 
 void sqlCharDynamicArray(char *s, char **retArray, int *retSize)
 /* Convert comma separated list of chars to a dynamically allocated
  * array, which should be freeMem()'d when done. Thread-safe. */
 {
 char *array = NULL;
 int count = 0;
 
 if (s)
     {
     count = countSeparatedItems(s, ',');
     if (count > 0)
 	{
 	AllocArray(array, count);
 	count = 0;
 	for (;;)
 	    {
 	    if (*s == ',')
 		errAbort("Empty element in list. Each element should contain one character.");
 	    array[count++] = *s++;
 	    if (!(*s == 0 || *s == ','))
 		{
 		--s;
 		char *e = strchr(s, ',');
 		if (e)
 		    *e = 0;
 		errAbort("Invalid character: %s", s);
 		}
 	    if (*s++ == 0)
 		break;
 	    if (*s == 0)
 		break;
 	    }
 	}
     }
 *retArray = array;
 *retSize = count;
 }
 
 /*-------------------------*/
 
 int sqlShortArray(char *s, short *array, int arraySize)
 /* Convert comma separated list of numbers to an array.  Pass in 
  * array an max size of array. */
 {
 unsigned count = 0;
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0 || count == arraySize)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     array[count++] = sqlSigned(s);
     s = e;
     }
 return count;
 }
 
 void sqlShortStaticArray(char *s, short **retArray, int *retSize)
 /* Convert comma separated list of numbers to an array which will be
  * overwritten next call to this function, but need not be freed. */
 {
 static short *array = NULL;
 static unsigned alloc = 0;
 unsigned count = 0;
 
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     if (count >= alloc)
 	{
 	if (alloc == 0)
 	    alloc = 64;
 	else
 	    alloc <<= 1;
 	ExpandArray(array, count, alloc);
 	}
     array[count++] = sqlSigned(s);
     s = e;
     }
 *retSize = count;
 *retArray = array;
 }
 
 void sqlShortDynamicArray(char *s, short **retArray, int *retSize)
 /* Convert comma separated list of numbers to an dynamically allocated
  * array, which should be freeMem()'d when done. Thread-safe. */
 {
 short *array = NULL;
 int count = 0;
 
 if (s)
     {
     count = countSeparatedItems(s, ',');
     if (count > 0)
 	{
 	AllocArray(array, count);
 	count = 0;
 	for (;;)
 	    {
 	    array[count++] = sqlSignedInList(&s);
 	    if (*s++ == 0)
 		break;
 	    if (*s == 0)
 		break;
 	    }
 	}
     }
 *retArray = array;
 *retSize = count;
 }
 
 /*-------------------------*/
 
 int sqlUshortArray(char *s, unsigned short *array, int arraySize)
 /* Convert comma separated list of numbers to an array.  Pass in 
  * array an max size of array. */
 {
 unsigned count = 0;
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0 || count == arraySize)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     array[count++] = sqlUnsigned(s);
     s = e;
     }
 return count;
 }
 
 void sqlUshortStaticArray(char *s, unsigned short **retArray, int *retSize)
 /* Convert comma separated list of numbers to an array which will be
  * overwritten next call to this function, but need not be freed. */
 {
 static unsigned short *array = NULL;
 static unsigned alloc = 0;
 unsigned count = 0;
 
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     if (count >= alloc)
 	{
 	if (alloc == 0)
 	    alloc = 64;
 	else
 	    alloc <<= 1;
 	ExpandArray(array, count, alloc);
 	}
     array[count++] = sqlUnsigned(s);
     s = e;
     }
 *retSize = count;
 *retArray = array;
 }
 
 void sqlUshortDynamicArray(char *s, unsigned short **retArray, int *retSize)
 /* Convert comma separated list of numbers to an dynamically allocated
  * array, which should be freeMem()'d when done. Thread-safe. */
 {
 unsigned short *array = NULL;
 int count = 0;
 
 if (s)
     {
     count = countSeparatedItems(s, ',');
     if (count > 0)
 	{
 	AllocArray(array, count);
 	count = 0;
 	for (;;)
 	    {
 	    array[count++] = sqlUnsignedInList(&s);
 	    if (*s++ == 0)
 		break;
 	    if (*s == 0)
 		break;
 	    }
 	}
     }
 *retArray = array;
 *retSize = count;
 }
 
 /*-------------------------*/
 int sqlDoubleArray(char *s, double *array, int maxArraySize)
 /* Convert comma separated list of floating point numbers to an array.  
  * Pass in array and max size of array. */
 {
 unsigned count = 0;
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0 || count == maxArraySize)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     array[count++] = atof(s);
     s = e;
     }
 return count;
 }
 
 double sqlSumDoublesCommaSep(char *s)
 /* Return sum of double values in a comma-separated list */
 {
 int count = 0;
 char *p = s;
 while (*p)
     if (*p++ == ',')
         count++;
 double *array = NULL;
 int arraySize = count + 1;
 AllocArray(array, arraySize);
 char *t = cloneString(s);
 count = sqlDoubleArray(cloneString(s), array, arraySize);
 freez(&t);
 int i;
 double sum = 0.0;
 for (i = 0; i < count; i++)
     sum += array[i];
 return sum;
 }
 
 int sqlFloatArray(char *s, float *array, int maxArraySize)
 /* Convert comma separated list of floating point numbers to an array.  
  * Pass in array and max size of array. */
 {
 unsigned count = 0;
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0 || count == maxArraySize)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     array[count++] = atof(s);
     s = e;
     }
 return count;
 }
 
 void sqlDoubleStaticArray(char *s, double **retArray, int *retSize)
 /* Convert comma separated list of numbers to an array which will be
  * overwritten next call to this function, but need not be freed. */
 {
 static double *array = NULL;
 static unsigned alloc = 0;
 unsigned count = 0;
 
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     if (count >= alloc)
 	{
 	if (alloc == 0)
 	    alloc = 64;
 	else
 	    alloc <<= 1;
 	ExpandArray(array, count, alloc);
 	}
     array[count++] = atof(s);
     s = e;
     }
 *retSize = count;
 *retArray = array;
 }
 
 void sqlFloatStaticArray(char *s, float **retArray, int *retSize)
 /* Convert comma separated list of numbers to an array which will be
  * overwritten next call to this function, but need not be freed. */
 {
 static float *array = NULL;
 static unsigned alloc = 0;
 unsigned count = 0;
 
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     if (count >= alloc)
 	{
 	if (alloc == 0)
 	    alloc = 128;
 	else
 	    alloc <<= 1;
 	ExpandArray(array, count, alloc);
 	}
     array[count++] = atof(s);
     s = e;
     }
 *retSize = count;
 *retArray = array;
 }
 
 void sqlDoubleDynamicArray(char *s, double **retArray, int *retSize)
 /* Convert comma separated list of numbers to an dynamically allocated
  * array, which should be freeMem()'d when done. Thread-safe.*/
 {
 double *array = NULL;
 int count = 0;
 
 if (s)
     {
     count = countSeparatedItems(s, ',');
     if (count > 0)
 	{
 	AllocArray(array, count);
 	count = 0;
 	for (;;)
 	    {
 	    array[count++] = sqlDoubleInList(&s);
 	    if (*s++ == 0)
 		break;
 	    if (*s == 0)
 		break;
 	    }
 	}
     }
 *retArray = array;
 *retSize = count;
 }
 
 void sqlFloatDynamicArray(char *s, float **retArray, int *retSize)
 /* Convert comma separated list of numbers to an dynamically allocated
  * array, which should be freeMem()'d when done. Thread-safe. */
 {
 float *array = NULL;
 int count = 0;
 
 if (s)
     {
     count = countSeparatedItems(s, ',');
     if (count > 0)
 	{
 	AllocArray(array, count);
 	count = 0;
 	for (;;)
 	    {
 	    array[count++] = sqlFloatInList(&s);
 	    if (*s++ == 0)
 		break;
 	    if (*s == 0)
 		break;
 	    }
 	}
     }
 *retArray = array;
 *retSize = count;
 }
 
 /*-------------------------*/
 
 int sqlUnsignedArray(char *s, unsigned *array, int arraySize)
 /* Convert comma separated list of numbers to an array.  Pass in 
  * array and max size of array. */
 {
 unsigned count = 0;
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0 || count == arraySize)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     array[count++] = sqlUnsigned(s);
     s = e;
     }
 return count;
 }
 
 void sqlUnsignedStaticArray(char *s, unsigned **retArray, int *retSize)
 /* Convert comma separated list of numbers to an array which will be
  * overwritten next call to this function, but need not be freed. */
 {
 static unsigned *array = NULL;
 static unsigned alloc = 0;
 unsigned count = 0;
 
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     if (count >= alloc)
 	{
 	if (alloc == 0)
 	    alloc = 64;
 	else
 	    alloc <<= 1;
 	ExpandArray(array, count, alloc);
 	}
     array[count++] = sqlUnsigned(s);
     s = e;
     }
 *retSize = count;
 *retArray = array;
 }
 
 void sqlUnsignedDynamicArray(char *s, unsigned **retArray, int *retSize)
 /* Convert comma separated list of numbers to an dynamically allocated
  * array, which should be freeMem()'d when done. Thread-safe. */
 {
 unsigned *array = NULL;
 int count = 0;
 
 if (s)
     {
     count = countSeparatedItems(s, ',');
     if (count > 0)
 	{
 	AllocArray(array, count);
 	count = 0;
 	for (;;)
 	    {
 	    array[count++] = sqlUnsignedInList(&s);
 	    if (*s++ == 0)
 		break;
 	    if (*s == 0)
 		break;
 	    }
 	}
     }
 *retArray = array;
 *retSize = count;
 }
 
 /*-------------------------*/
 
 int sqlSignedArray(char *s, int *array, int arraySize)
 /* Convert comma separated list of numbers to an array.  Pass in 
  * array an max size of array. */
 {
 int count = 0;
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0 || count == arraySize)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     array[count++] = sqlSigned(s);
     s = e;
     }
 return count;
 }
 
 void sqlSignedStaticArray(char *s, int **retArray, int *retSize)
 /* Convert comma separated list of numbers to an array which will be
  * overwritten next call to this function, but need not be freed. */
 {
 static int *array = NULL;
 static int alloc = 0;
 int count = 0;
 
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     if (count >= alloc)
 	{
 	if (alloc == 0)
 	    alloc = 64;
 	else
 	    alloc <<= 1;
 	ExpandArray(array, count, alloc);
 	}
     array[count++] = sqlSigned(s);
     s = e;
     }
 *retSize = count;
 *retArray = array;
 }
 
 void sqlSignedDynamicArray(char *s, int **retArray, int *retSize)
 /* Convert comma separated list of numbers to an dynamically allocated
  * array, which should be freeMem()'d when done. Thread-safe. */
 {
 int *array = NULL;
 int count = 0;
 
 if (s)
     {
     count = countSeparatedItems(s, ',');
     if (count > 0)
 	{
 	AllocArray(array, count);
 	count = 0;
 	for (;;)
 	    {
 	    array[count++] = sqlSignedInList(&s);
 	    if (*s++ == 0)
 		break;
 	    if (*s == 0)
 		break;
 	    }
 	}
     }
 *retArray = array;
 *retSize = count;
 }
 
 
 /*-------------------------*/
 
 int sqlLongLongArray(char *s, long long *array, int arraySize)
 /* Convert comma separated list of numbers to an array.  Pass in 
  * array and max size of array. */
 {
 unsigned count = 0;
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0 || count == arraySize)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     array[count++] = sqlLongLong(s);
     s = e;
     }
 return count;
 }
 
 void sqlLongLongStaticArray(char *s, long long **retArray, int *retSize)
 /* Convert comma separated list of numbers to an array which will be
  * overwritten next call to this function, but need not be freed. */
 {
 static long long *array = NULL;
 static unsigned alloc = 0;
 unsigned count = 0;
 
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     if (count >= alloc)
 	{
 	if (alloc == 0)
 	    alloc = 64;
 	else
 	    alloc <<= 1;
 	ExpandArray(array, count, alloc);
 	}
     array[count++] = sqlLongLong(s);
     s = e;
     }
 *retSize = count;
 *retArray = array;
 }
 
 void sqlLongLongDynamicArray(char *s, long long **retArray, int *retSize)
 /* Convert comma separated list of numbers to an dynamically allocated
  * array, which should be freeMem()'d when done. Thread-safe. */
 {
 long long *array = NULL;
 int count = 0;
 
 if (s)
     {
     count = countSeparatedItems(s, ',');
     if (count > 0)
 	{
 	AllocArray(array, count);
 	count = 0;
 	for (;;)
 	    {
 	    array[count++] = sqlLongLongInList(&s);
 	    if (*s++ == 0)
 		break;
 	    if (*s == 0)
 		break;
 	    }
 	}
     }
 *retArray = array;
 *retSize = count;
 }
 
 /*-------------------------*/
 
 
 int sqlStringArray(char *s, char **array, int maxArraySize)
 /* Convert comma separated list of strings to an array.  Pass in 
  * array and max size of array.  Returns actual size*/
 {
 int count = 0;
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0 || count == maxArraySize)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     array[count++] = s;
     s = e;
     }
 return count;
 }
 
 void sqlStringStaticArray(char *s, char  ***retArray, int *retSize)
 /* Convert comma separated list of strings to an array which will be
  * overwritten next call to this function,  but need not be freed. */
 {
 static char **array = NULL;
 static int alloc = 0;
 int count = 0;
 
 for (;;)
     {
     char *e;
     if (s == NULL || s[0] == 0)
 	break;
     e = strchr(s, ',');
     if (e != NULL)
 	*e++ = 0;
     if (count >= alloc)
 	{
 	if (alloc == 0)
 	    alloc = 64;
 	else
 	    alloc <<= 1;
 	ExpandArray(array, count, alloc);
 	}
     array[count++] = s;
     s = e;
     }
 *retSize = count;
 *retArray = array;
 }
 
 void sqlStringDynamicArray(char *s, char ***retArray, int *retSize)
 /* Convert comma separated list of strings to an dynamically allocated
  * array, which should be freeMem()'d when done. As a speed option all
  * of the elements in the array are needMem()'d at the same time. This 
  * means that all the entries are free()'d by calling freeMem() on the
  * first element. For example:
  * sqlStringDynamicArray(s, &retArray, &retSize);
  * DoSomeFunction(retArray, retSize);
  * freeMem(retArray[0]);
  * freeMem(retArray);
  * Thread-safe. */
 {
 char **array = NULL;
 int count = 0;
 if (s)
     {
     count = countSeparatedItems(s, ',');
     if (count > 0)
 	{
 	AllocArray(array, count);
 	count = 0;
 	s = cloneString(s);
 	for (;;)
 	    {
 	    char *e;
 	    if (s == NULL || s[0] == 0)
 		break;
 	    e = strchr(s, ',');
 	    if (e != NULL)
 		*e++ = 0;
 	    array[count++] = s;
 	    s = e;
 	    }
 	}
     }
 *retArray = array;
 *retSize = count;
 }
 
 char *sqlDoubleArrayToString( double *array, int arraySize)
 {
 int i;
 struct dyString *string = dyStringNew(256);
 for( i = 0 ; i < arraySize; i++ )
     {
     dyStringPrintf(string, "%f,", array[i]);
     }
 return dyStringCannibalize(&string);
 }
 
 char *sqlFloatArrayToString( float *array, int arraySize)
 {
 int i;
 struct dyString *string = dyStringNew(256);
 for( i = 0 ; i < arraySize; i++ )
     {
     dyStringPrintf(string, "%f,", array[i]);
     }
 return dyStringCannibalize(&string);
 }
 
 char *sqlUnsignedArrayToString( unsigned *array, int arraySize)
 {
 int i;
 struct dyString *string = dyStringNew(256);
 for( i = 0 ; i < arraySize; i++ )
     {
     dyStringPrintf(string, "%u,", array[i]);
     }
 return dyStringCannibalize(&string);
 }
 
 char *sqlSignedArrayToString( int *array, int arraySize)
 {
 int i;
 struct dyString *string = dyStringNew(256);
 for( i = 0 ; i < arraySize; i++ )
     {
     dyStringPrintf(string, "%d,", array[i]);
     }
 return dyStringCannibalize(&string);
 }
 
 char *sqlShortArrayToString( short *array, int arraySize)
 {
 int i;
 struct dyString *string = dyStringNew(256);
 for( i = 0 ; i < arraySize; i++ )
     {
     dyStringPrintf(string, "%d,", array[i]);
     }
 return dyStringCannibalize(&string);
 }
 
 char *sqlUshortArrayToString( unsigned short *array, int arraySize)
 {
 int i;
 struct dyString *string = dyStringNew(256);
 for( i = 0 ; i < arraySize; i++ )
     {
     dyStringPrintf(string, "%u,", array[i]);
     }
 return dyStringCannibalize(&string);
 }
 
 char *sqlByteArrayToString( signed char *array, int arraySize)
 {
 int i;
 struct dyString *string = dyStringNew(256);
 for( i = 0 ; i < arraySize; i++ )
     {
     dyStringPrintf(string, "%d,", array[i]);
     }
 return dyStringCannibalize(&string);
 }
 
 char *sqlUbyteArrayToString( unsigned char *array, int arraySize)
 {
 int i;
 struct dyString *string = dyStringNew(256);
 for( i = 0 ; i < arraySize; i++ )
     {
     dyStringPrintf(string, "%u,", array[i]);
     }
 return dyStringCannibalize(&string);
 }
 
 char *sqlCharArrayToString( char *array, int arraySize)
 {
 int i;
 struct dyString *string = dyStringNew(256);
 for( i = 0 ; i < arraySize; i++ )
     {
     dyStringPrintf(string, "%c,", array[i]);
     }
 return dyStringCannibalize(&string);
 }
 
 char *sqlLongLongArrayToString( long long *array, int arraySize)
 {
 int i;
 struct dyString *string = dyStringNew(256);
 for( i = 0 ; i < arraySize; i++ )
     {
     dyStringPrintf(string, "%lld,", array[i]);
     }
 return dyStringCannibalize(&string);
 }
 
 char *sqlStringArrayToString( char **array, int arraySize)
 {
 int i;
 struct dyString *string = dyStringNew(256);
 for( i = 0 ; i < arraySize; i++ )
     {
     dyStringPrintf(string, "%s,", array[i]);
     }
 return dyStringCannibalize(&string);
 }
 
 
 /* -------------- */
 
 
 
 void sqlStringFreeDynamicArray(char ***pArray)
 /* Free up a dynamic array (ends up freeing array and first string on it.) */
 {
 char **array;
 if ((array = *pArray) != NULL)
     {
     freeMem(array[0]);
     freez(pArray);
     }
 }
 
 int sqlUnsignedComma(char **pS)
 /* Return signed number at *pS.  Advance *pS past comma at end */
 {
 char *s = *pS;
 char *e = strchr(s, ',');
 unsigned ret;
 
 *e++ = 0;
 *pS = e;
 ret = sqlUnsigned(s);
 return ret;
 }
 
+unsigned long sqlUnsignedLongComma(char **pS)
+/* Return unsigned long number at *pS.  Advance *pS past comma at end */
+{
+char *s = *pS;
+char *e = strchr(s, ',');
+unsigned long ret;
+
+*e++ = 0;
+*pS = e;
+ret = sqlUnsignedLong(s);
+return ret;
+}
 
 int sqlSignedComma(char **pS)
 /* Return signed number at *pS.  Advance *pS past comma at end */
 {
 char *s = *pS;
 char *e = strchr(s, ',');
 int ret;
 
 *e++ = 0;
 *pS = e;
 ret = sqlSigned(s);
 return ret;
 }
 
 char sqlCharComma(char **pS)
 /* Return char at *pS.  Advance *pS past comma after char */
 {
 char *s = *pS;
 char *e = strchr(s, ',');
 int ret;
 
 *e++ = 0;
 *pS = e;
 ret = s[0];
 return ret;
 }
 
 long long sqlLongLongComma(char **pS)
 /* Return offset (often 64 bits) at *pS.  Advance *pS past comma at 
  * end */
 {
 char *s = *pS;
 char *e = strchr(s, ',');
 long long ret;
 
 *e++ = 0;
 *pS = e;
 ret = sqlLongLong(s);
 return ret;
 }
 
 float sqlFloatComma(char **pS)
 /* Return signed number at *pS.  Advance *pS past comma at end */
 {
 char *s = *pS;
 char *e = strchr(s, ',');
 float ret;
 
 *e++ = 0;
 *pS = e;
 ret = atof(s);
 return ret;
 }
 
 double sqlDoubleComma(char **pS)
 /* Return signed number at *pS.  Advance *pS past comma at end */
 {
 char *s = *pS;
 char *e = strchr(s, ',');
 double ret;
 
 *e++ = 0;
 *pS = e;
 ret = atof(s);
 return ret;
 }
 
 
 static char *findStringEnd(char *start, char endC)
 /* Return end of string. */
 {
 char c;
 char *s = start;
 
 for (;;)
     {
     c = *s;
     if (c == endC)
 	return s;
     else if (c == 0)
 	errAbort("Unterminated string");
     ++s;
     }
 }
 
 static char *sqlGetOptQuoteString(char **pS)
 /* Return string at *pS.  (Either quoted or not.)  Advance *pS. */
 {
 char *s = *pS;
 char *e;
 char c = *s;
 
 if (c  == '"' || c == '\'')
     {
     s += 1;
     e = findStringEnd(s, c);
     *e++ = 0;
     if (*e++ != ',')
 	errAbort("Expecting comma after string");
     }
 else
     {
     e = strchr(s, ',');
     *e++ = 0;
     }
 *pS = e;
 return s;
 }
 
 char *sqlStringComma(char **pS)
 /* Return string at *pS.  (Either quoted or not.)  Advance *pS. */
 {
 return cloneString(sqlGetOptQuoteString(pS));
 }
 
 void sqlFixedStringComma(char **pS, char *buf, int bufSize)
 /* Copy string at *pS to buf.  Advance *pS. */
 {
 strncpy(buf, sqlGetOptQuoteString(pS), bufSize);
 }
 
 char *sqlEatChar(char *s, char c)
 /* Make sure next character is 'c'.  Return past next char */
 {
 if (*s++ != c)
     errAbort("Expecting %c got %c (%d) in database", c, s[-1], s[-1]);
 return s;
 }
 
 static struct hash *buildSymHash(char **values, boolean isEnum)
 /* build a hash of values for either enum or set symbolic column */
 {
 struct hash *valHash = hashNew(0);
 unsigned setVal = 1; /* not used for enum */
 int iVal;
 for (iVal = 0; values[iVal] != NULL; iVal++)
     {
     if (isEnum)
         hashAddInt(valHash, values[iVal], iVal);
     else
         {
         hashAddInt(valHash, values[iVal], setVal);
         setVal = setVal << 1;
         }
     }
 return valHash;
 }
 
 unsigned sqlEnumParse(char *valStr, char **values, struct hash **valHashPtr)
 /* parse an enumerated column value */
 {
 if (*valHashPtr == NULL)
     *valHashPtr = buildSymHash(values, TRUE);
 return hashIntVal(*valHashPtr, valStr);
 }
 
 unsigned sqlEnumComma(char **pS, char **values, struct hash **valHashPtr)
 /* Return enum at *pS.  (Either quoted or not.)  Advance *pS. */
 {
 return sqlEnumParse(sqlGetOptQuoteString(pS), values, valHashPtr);
 }
 
 void sqlEnumPrint(FILE *f, unsigned value, char **values)
 /* print an enumerated column value */
 {
 fputs(values[value], f);
 }
 
 unsigned sqlSetParse(char *valStr, char **values, struct hash **valHashPtr)
 /* parse a set column value */
 {
 if (*valHashPtr == NULL)
     *valHashPtr = buildSymHash(values, FALSE);
 /* parse comma separated string */
 unsigned value = 0;
 char *val = strtok(valStr, ",");
 while (val != NULL)
     {
     value |= hashIntVal(*valHashPtr, val);
     val = strtok(NULL, ",");
     }
 
 return value;
 }
 
 unsigned sqlSetComma(char **pS, char **values, struct hash **valHashPtr)
 /* Return set at *pS.  (Either quoted or not.)  Advance *pS. */
 {
 return sqlSetParse(sqlGetOptQuoteString(pS), values, valHashPtr);
 }
 
 void sqlSetPrint(FILE *f, unsigned value, char **values)
 /* print a set column value */
 {
 int iVal;
 unsigned curVal = 1;
 int cnt = 0;
 for (iVal = 0; values[iVal] != NULL; iVal++, curVal = curVal << 1)
     {
     if (curVal & value)
         {
         if (cnt > 0)
             fputc(',', f);
         fputs(values[iVal], f);
         cnt++;
         }
     }
 }