IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jun 2, 2006, 9:21:49 AM (20 years ago)
Author:
Paul Price
Message:

Applying patch from Josh: adds 'or' conditional support to psDB where clauses

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/db/psDB.c

    r7143 r7294  
    1212 *  @author Joshua Hoblitt
    1313 *
    14  *  @version $Revision: 1.52 $ $Name: not supported by cvs2svn $
    15  *  @date $Date: 2006-05-18 20:08:33 $
     14 *  @version $Revision: 1.53 $ $Name: not supported by cvs2svn $
     15 *  @date $Date: 2006-06-02 19:21:49 $
    1616 *
    1717 *  Copyright 2005 Joshua Hoblitt, University of Hawaii
     
    6464static char    *psDBGenerateSetSQL(const psMetadata *set
    6565                                  );
     66static char    *psDBGenerateConditionalSQL(const psMetadataItem *item);
    6667// lookup table functions
    6768static psElemType psDBMySQLToPType(enum enum_field_types type, unsigned int flags);
     
    13501351{
    13511352    char            *query = NULL;
    1352     psListIterator  *cursor;
    1353     psMetadataItem  *item;
    13541353
    13551354    if (!where) {
     
    13601359    query = psStringCopy("WHERE ");
    13611360
    1362     cursor = psListIteratorAlloc(where->list, 0, false);
     1361    // we need to know if an item is 'MULTI' so we have to march through the
     1362    // list by key name and not by items
     1363    psList *keys = psHashKeyList(where->hash);
     1364    psListIterator *cursor = psListIteratorAlloc(keys, 0, false);
    13631365
    13641366    // find column name and match pattern
    1365     while ((item = psListGetAndIncrement(cursor))) {
    1366         // item->data must be a string
    1367         if ((item->type == PS_DATA_S32) || (item->type == PS_TYPE_S32)) {
    1368             psStringAppend(&query, "%s=%d", item->name, (int)(item->data.S32));
    1369         } else if ((item->type == PS_DATA_F32) || (item->type == PS_TYPE_F32)) {
    1370             psStringAppend(&query, "%s=%g", item->name, (double)(item->data.F32));
    1371         } else if ((item->type == PS_DATA_F64) || (item->type == PS_TYPE_F64)) {
    1372             psStringAppend(&query, "%s=%g", item->name, (double)(item->data.F64));
    1373         } else if ((item->type == PS_DATA_BOOL) || (item->type == PS_TYPE_BOOL)) {
    1374             psStringAppend(&query, "%s=%d", item->name, (int)(item->data.B));
    1375         } else if (item->type == PS_DATA_STRING) {
    1376             // + column name + _ + like + _ + ' + value + '
    1377             // check for NULL and empty ("") strings
    1378             if (item->data.V == NULL || *(char *)item->data.V == '\0') {
    1379                 psStringAppend(&query, "%s IS NULL", item->name);
    1380             } else {
    1381                 // XXX ASC NOTE: we should have a better match for
    1382                 // char & varchar columns than this.  LIKE is OK for
    1383                 // very large TEXT columns that really shouldn't be
    1384                 // used in a where clause...
    1385                 psStringAppend(&query, "%s LIKE '%s'", item->name, item->data.V);
     1367    psString itemName = NULL;
     1368    while ((itemName = psListGetAndIncrement(cursor))) {
     1369        psMetadataItem *item = psMetadataLookup(where, itemName);
     1370
     1371        if (item->type == PS_DATA_METADATA_MULTI) {
     1372            char *logicalOp = "AND";
     1373
     1374            // scan through the list and change the logicalOp joining
     1375            // conditionals together to "OR" if a comment of "==" is found
     1376            psListIterator *mCursor = psListIteratorAlloc(item->data.list, 0,
     1377                                      false);
     1378            psMetadataItem *mItem = NULL;
     1379            while ((mItem = psListGetAndIncrement(mCursor))) {
     1380                if (mItem->comment && strstr(mItem->comment, "==")) {
     1381                    logicalOp = "OR";
     1382                    break;
     1383                }
    13861384            }
     1385
     1386            // "(" + conditional [ + " AND/OR " + conditional ] + ")"
     1387            // reset the iterator
     1388            psListIteratorSet(mCursor, 0);
     1389            psStringAppend(&query, "(");
     1390            while ((mItem = psListGetAndIncrement(mCursor))) {
     1391                char *conditional = psDBGenerateConditionalSQL(mItem);
     1392                if (!conditional) {
     1393                    psError(PS_ERR_UNKNOWN, false,
     1394                            "SQL conditional generation failed.");
     1395                    psFree(mCursor);
     1396                    psFree(cursor);
     1397                    psFree(keys);
     1398                    psFree(query);
     1399                    return NULL;
     1400                }
     1401
     1402                psStringAppend(&query, "%s", conditional);
     1403                psFree(conditional);
     1404
     1405                // + " AND/OR "
     1406                if (!mCursor->offEnd) {
     1407                    psStringAppend(&query, " %s ", logicalOp);
     1408                }
     1409
     1410            }
     1411            psFree(mCursor);
     1412
     1413            psStringAppend(&query, ")");
    13871414        } else {
    1388             psError(PS_ERR_BAD_PARAMETER_TYPE, true,
    1389                     "Only types PS_DATA_S32, PS_DATA_F32, PS_DATA_F64, PS_DATA_BOOL, PS_DATA_STRING are supported");
    1390 
    1391             psFree(cursor);
    1392             psFree(query);
    1393 
    1394             return NULL;
    1395         }
    1396 
    1397         // + " and " after every column declaration except the last one
    1398         if (!cursor->offEnd) {
    1399             psStringAppend(&query, " AND ");
    1400         }
    1401     }
    1402 
    1403     psFree(cursor);
     1415            char *conditional = psDBGenerateConditionalSQL(item);
     1416            if (!conditional) {
     1417                psError(PS_ERR_UNKNOWN, false,
     1418                        "SQL conditional generation failed.");
     1419                psFree(cursor);
     1420                psFree(keys);
     1421                psFree(query);
     1422                return NULL;
     1423            }
     1424
     1425            psStringAppend(&query, "%s", conditional);
     1426            psFree(conditional);
     1427
     1428            // + " and " after every column declaration except the last one
     1429            if (!cursor->offEnd) {
     1430                psStringAppend(&query, " AND ");
     1431            }
     1432        }
     1433    }
     1434
     1435    //    psFree(cursor);
     1436    psFree(keys);
    14041437
    14051438    return query;
     
    14371470
    14381471    psFree(cursor);
     1472
     1473    return query;
     1474}
     1475
     1476static char *psDBGenerateConditionalSQL(const psMetadataItem *item)
     1477{
     1478    char            *query = NULL;
     1479
     1480    PS_ASSERT_PTR_NON_NULL(item, NULL);
     1481
     1482    // stringify the psMetadataItem into a SQL search specification
     1483    if ((item->type == PS_DATA_S32) || (item->type == PS_TYPE_S32)) {
     1484        psStringAppend(&query, "%s=%d", item->name, (int)(item->data.S32));
     1485    } else if ((item->type == PS_DATA_F32) || (item->type == PS_TYPE_F32)) {
     1486        psStringAppend(&query, "%s=%g", item->name, (double)(item->data.F32));
     1487    } else if ((item->type == PS_DATA_F64) || (item->type == PS_TYPE_F64)) {
     1488        psStringAppend(&query, "%s=%g", item->name, (double)(item->data.F64));
     1489    } else if ((item->type == PS_DATA_BOOL) || (item->type == PS_TYPE_BOOL)) {
     1490        psStringAppend(&query, "%s=%d", item->name, (int)(item->data.B));
     1491    } else if (item->type == PS_DATA_STRING) {
     1492        // + column name + _ + like + _ + ' + value + '
     1493        // check for NULL and empty ("") strings
     1494        if (item->data.V == NULL || *(char *)item->data.V == '\0') {
     1495            psStringAppend(&query, "%s IS NULL", item->name);
     1496        } else {
     1497            // XXX ASC NOTE: we should have a better match for
     1498            // char & varchar columns than this.  LIKE is OK for
     1499            // very large TEXT columns that really shouldn't be
     1500            // used in a where clause...
     1501            psStringAppend(&query, "%s LIKE '%s'", item->name, item->data.V);
     1502        }
     1503    } else {
     1504        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
     1505                "Only types PS_DATA_S32, PS_DATA_F32, PS_DATA_F64, PS_DATA_BOOL, PS_DATA_STRING are supported");
     1506
     1507        return NULL;
     1508    }
    14391509
    14401510    return query;
Note: See TracChangeset for help on using the changeset viewer.