Index: trunk/psLib/src/db/psDB.c
===================================================================
--- trunk/psLib/src/db/psDB.c	(revision 10708)
+++ trunk/psLib/src/db/psDB.c	(revision 10737)
@@ -12,6 +12,6 @@
  *  @author Joshua Hoblitt
  *
- *  @version $Revision: 1.122 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-12-14 05:13:58 $
+ *  @version $Revision: 1.123 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-12-14 23:03:40 $
  *
  *  Copyright (C) 2005-2006  Joshua Hoblitt, University of Hawaii
@@ -1864,4 +1864,15 @@
 }
 
+typedef enum {
+    PS_DB_OP_EQ,
+    PS_DB_OP_LT,
+    PS_DB_OP_GT,
+    PS_DB_OP_LE,
+    PS_DB_OP_GE,
+} psDBOpValue;
+
+# define PS_DB_FLT_PAD (FLT_EPSILON * 10)
+# define PS_DB_DBL_PAD (DBL_EPSILON * 10)
+
 static psString psDBGenerateConditionalSQL(const psMetadataItem *item, const char *tableName)
 {
@@ -1890,32 +1901,82 @@
 
     // default to exact match ('=')
-    char *op = "=";
+    char *opStr = "=";
+    psDBOpValue op = PS_DB_OP_EQ;
     if (item->comment) {
         // arbitrary semantic, precedence is: >=, <=, >, <, = (default)
         if (strstr(item->comment, ">=")) {
-            op = ">=";
+            opStr = ">=";
+            op = PS_DB_OP_GE;
         } else if (strstr(item->comment, "<=")) {
-            op = "<=";
+            opStr = "<=";
+            op = PS_DB_OP_LE;
         } else if (strstr(item->comment, ">")) {
-            op = ">";
+            opStr = ">";
+            op = PS_DB_OP_GT;
         } else if (strstr(item->comment, "<")) {
-            op = "<";
-        }
-    }
+            opStr = "<";
+            op = PS_DB_OP_LT;
+        }
+    }
+
+    // XXX why are >, < searches not supported here????
+    // fix this immediately!!
+    // for datetime comparisons, we need to use single-quotes around the string value:
+    // where dateobs < '2002-09-06' and dateobs > '2002-09-05,15:40:22'
 
     switch (item->type) {
     case PS_DATA_S32:
-        psStringAppend(&query, "%s %s %d", itemName, op, (int)(item->data.S32));
+        // the raw opStr is good enough in the query
+        psStringAppend(&query, "%s %s %d", itemName, opStr, (int)(item->data.S32));
         break;
     case PS_DATA_F32:
-        psStringAppend(&query, "(ABS(%s - %.8f) < %.8f)", itemName, (float)(item->data.F32), FLT_EPSILON * 10);
+        // need to handle floating-point round-off issues (use a padding of 10*FLT_EPSILON)
+        switch (op) {
+        case PS_DB_OP_EQ:
+            psStringAppend(&query, "(ABS(%s - %.8f) < %.8f)", itemName, (float)(item->data.F32), PS_DB_FLT_PAD);
+            break;
+        case PS_DB_OP_LE:
+        case PS_DB_OP_LT:
+            // A < B becomes A < B + epsilon
+            psStringAppend(&query, "(%s < %.8f + %.8f)", itemName, (float)(item->data.F32), PS_DB_FLT_PAD);
+            break;
+        case PS_DB_OP_GE:
+        case PS_DB_OP_GT:
+            // A > B becomes A > B - epsilon
+            psStringAppend(&query, "(%s > %.8f - %.8f)", itemName, (float)(item->data.F32), PS_DB_FLT_PAD);
+            break;
+        }
         break;
     case PS_DATA_F64:
-        psStringAppend(&query, "(ABS(%s - %.17f) < %.17f)", itemName, (double)(item->data.F64), DBL_EPSILON * 10);
+        // need to handle floating-point round-off issues (use a padding of 10*FLT_EPSILON)
+        switch (op) {
+        case PS_DB_OP_EQ:
+            psStringAppend(&query, "(ABS(%s - %.17f) < %.17f)", itemName, (float)(item->data.F64), PS_DB_DBL_PAD);
+            break;
+        case PS_DB_OP_LE:
+        case PS_DB_OP_LT:
+            // A < B becomes A < B + epsilon
+            psStringAppend(&query, "(%s < %.17f + %.17f)", itemName, (float)(item->data.F64), PS_DB_DBL_PAD);
+            break;
+        case PS_DB_OP_GE:
+        case PS_DB_OP_GT:
+            // A > B becomes A > B - epsilon
+            psStringAppend(&query, "(%s > %.17f - %.17f)", itemName, (float)(item->data.F64), PS_DB_DBL_PAD);
+            break;
+        }
         break;
     case PS_DATA_BOOL:
-        psStringAppend(&query, "%s = %d", itemName, (int)(item->data.B));
+        switch (op) {
+        case PS_DB_OP_EQ:
+            psStringAppend(&query, "%s = %d", itemName, (int)(item->data.B));
+            break;
+        default:
+            psError(PS_ERR_UNKNOWN, true, "NULL psBool can't be compared with any operator other than '=='");
+            psFree(itemName);
+            return NULL;
+        }
         break;
     case PS_DATA_STRING:
+        // XXX EAM : probably need to add some regex-like operations here
         // + column name + _ + like + _ + ' + value + '
         // check for NULL and empty ("") strings
@@ -1937,10 +1998,10 @@
             if (item->data.V) {
                 psString timeStr = psTimeToISO(item->data.V);
-                psStringAppend(&query, "%s %s '%s'", itemName, op, timeStr);
+                psStringAppend(&query, "%s %s '%s'", itemName, opStr, timeStr);
                 psFree(timeStr);
-            } else if (strstr(op, "=")) {
+            } else if (strstr(opStr, "=")) {
                 psStringAppend(&query, "%s IS NULL", itemName);
             } else {
-                psError(PS_ERR_UNKNOWN, true, "NULL psTime can't be compared with any operator other than '=='");
+                psError(PS_ERR_UNKNOWN, true, "psTime comparison value is NULL: A NULL psTime value can't be compared with any operator other than '=='");
                 psFree(itemName);
                 return NULL;
