IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 43004


Ignore:
Timestamp:
May 2, 2026, 3:48:37 PM (5 days ago)
Author:
eugene
Message:

plug a leak in p_psDBRunQueryPrepared; add function to free prepared queries (for general cleanup); init the MYSQL_TIME structure (or time types break); fractional part in query is in microseconds, not nanoseconds; do not delete all rows if a limit is provided; fix tap test to take database info from args; fix tap tests to work in Ubuntu 22.04 / MySQL 8.0

Location:
branches/eam_branches/ipp-pstamp-20260421/psLib
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-pstamp-20260421/psLib/src/db/psDB.c

    r42826 r43004  
    713713
    714714    // Create SQL statement string
    715     psString query = psDBGenerateDeleteRowSQL(tableName, where,limit);
     715    psString query = psDBGenerateDeleteRowSQL(tableName, where, limit);
    716716    if (!query) {
    717717        psError(PS_ERR_UNEXPECTED_NULL, false, "Query generation failed.");
     
    871871}
    872872
     873bool psDBFreeQueryPrepared (void) {
     874
     875    // initalize the prepared query cache
     876    if (!preparedQuery) {
     877      return true;
     878    }
     879
     880    // start lock on query cache
     881    if (psMemGetThreadSafety()) {
     882        pthread_mutex_lock(&preparedQueryMutex);
     883    }
     884
     885    psFree (preparedQuery);
     886    preparedQuery = NULL;
     887
     888    pthread_mutex_unlock(&preparedQueryMutex);
     889
     890    return true;
     891}
     892
    873893long p_psDBRunQueryPrepared(psDB *dbh,
    874894                            const psArray *rowSet,
     
    918938        // add this statement to the cache
    919939        psHashAdd(preparedQuery, query, stmt);
     940        psFree (stmt);
    920941    } else {
    921942        psTrace("psLib.db", PS_LOG_INFO, "found statment in query cache");
     
    16081629                    // have to be free'd
    16091630                    MYSQL_TIME *myTime = psAlloc(sizeof(MYSQL_TIME));
     1631                    memset(myTime, 0, sizeof(MYSQL_TIME));
     1632                   
    16101633                    myTime->year    = (unsigned int)tmTime->tm_year + 1900;
    16111634                    myTime->month   = (unsigned int)tmTime->tm_mon + 1;
     
    16191642                    // in 5.0 and 5.6, my_bool is char
    16201643                    myTime->neg     = (bool)false;
    1621                     // currently unused by mysql
    1622                     myTime->second_part  = (unsigned long)time->nsec;
     1644
     1645                    // MySQL expects fractional seconds in microseconds, not nanoseconds
     1646                    myTime->second_part = (unsigned long)(time->nsec / 1000);
     1647
     1648                    // XXX remove: currently unused by mysql
     1649                    // myTime->second_part  = (unsigned long)time->nsec;
     1650
    16231651                    psFree(tmTime);
    16241652
    16251653                    bind[i].buffer  = myTime;
    16261654                    bind[i].buffer_length = sizeof(MYSQL_TIME);
    1627                     bind[i].length  = &bind[i].buffer_length;
     1655                    // XXX bind[i].length  = &bind[i].buffer_length;
     1656                    bind[i].length  = 0;
    16281657                    bind[i].is_null = NULL;
    16291658                } else {
     
    21292158    char            *limitString;
    21302159
    2131     // delete all rows if where is NULL
    2132     if (!where) {
     2160    // delete all rows if WHERE is NULL and no limit is given (limit == 0)
     2161    if (!where && !limit) {
    21332162        psStringAppend(&query, "TRUNCATE TABLE %s", tableName);
    21342163        return query;
    21352164    }
    21362165
    2137     // Generate where SQL substring
    2138     whereSQL = psDBGenerateWhereSQL(where, tableName);
    2139     if (!whereSQL) {
     2166    psStringAppend(&query, "DELETE FROM %s", tableName);
     2167
     2168    if (where) {
     2169      // Generate where SQL substring
     2170      whereSQL = psDBGenerateWhereSQL(where, tableName);
     2171      if (!whereSQL) {
    21402172        psError(PS_ERR_UNEXPECTED_NULL, false, _("SQL substring generation failed."));
    21412173        return NULL;
    2142     }
    2143 
    2144     psStringAppend(&query, "DELETE FROM %s %s", tableName, whereSQL);
     2174      }
     2175      psStringAppend(&query, " %s", whereSQL);
     2176      psFree(whereSQL);
     2177    }
    21452178
    21462179    // Complete delete SQL command string
     
    21512184        psFree(limitString);
    21522185    }
    2153     psFree(whereSQL);
    21542186
    21552187    return query;
     
    29452977
    29462978#endif // HAVE_PSDB
     2979
  • branches/eam_branches/ipp-pstamp-20260421/psLib/src/db/psDB.h

    r21401 r43004  
    174174    const char *query                   ///< SQL string to execute
    175175);
     176
     177/** Free all prepared queries
     178 * dialect is provided.  Caveat emptor.
     179 *
     180 * @return long:    the number of database rows affected
     181 */
     182bool psDBFreeQueryPrepared(void);
    176183
    177184/** Fetches the result of a SQL query
  • branches/eam_branches/ipp-pstamp-20260421/psLib/test/db/tap_psDB.c

    r12607 r43004  
    2121
    2222#define HOST    "localhost"
    23 #define USER    "test"
    24 #define PASSWD  ""
    25 #define DBNAME  "test"
    2623#define PORT    0
     24
     25static char *USER = "";
     26static char *PASSWD = "";
     27static char *DBNAME = "";
     28
     29# define DEBUG 0
    2730
    2831int main(int argc, char* argv[])
     
    3336#endif
    3437
    35     plan_tests(34 + 1);
     38    plan_tests(53);
     39
     40    ok(argc == 4, "USAGE: %s USER PASSWD DBNAME", argv[0]);
     41    if (argc != 4) { done(); }
     42
     43    USER = argv[1];
     44    PASSWD = argv[2];
     45    DBNAME = argv[3];
    3646
    3747    // see if we can open a db connection at all
    38     {
     48    if (1) {
    3949        psDB *dbh = psDBInit(HOST, USER, PASSWD, DBNAME, PORT);
    4050        ok(dbh, "open a database handle");
    41         if (!dbh) {
    42             done();
    43         }
     51        if (!dbh) { done(); }
    4452        psFree(dbh);
    4553    }
    4654
    47     // test new database creation
    48     // the next 3 tests will fail as the MySQL test account has insufficent
    49     // permissions
    50     {
    51         psDB *dbh = psDBInit(HOST, USER, PASSWD, DBNAME, PORT);
    52 
    53         skip_start(!psDBCreate(dbh, "foobar"), 4,
    54                 "you probably don't have proper database permissions");
    55         ok(psDBCreate(dbh, "foobar"), "psDBCreate()");
     55    // Test new database creation. The next 3 tests will fail if the MySQL test account
     56    // has insufficent permissions
     57    if (1) {
     58        psDB *dbh = psDBInit(HOST, USER, PASSWD, DBNAME, PORT);
     59        ok(dbh, "re-open a database handle");
     60
     61        skip_start(!psDBCreate(dbh, "foobar"), 4, "you probably don't have proper database permissions");
    5662        ok(psDBChange(dbh, "foobar"), "psDBChange()");
    5763        ok(psDBDrop(dbh, "foobar"), "psDBDrop()");
     
    6470
    6571    // psDBCreateTable() & psDBDropTable()
    66     {
    67         psDB *dbh = psDBInit(HOST, USER, PASSWD, DBNAME, PORT);
     72    if (1) {
     73        psDB *dbh = psDBInit(HOST, USER, PASSWD, DBNAME, PORT);
     74        ok(dbh, "re-open a database handle");
     75
    6876        psMetadata *md = psMetadataAlloc();
    6977        psMetadataAdd(md, PS_LIST_TAIL, "foo", PS_DATA_S32, "Primary Key", 0);
     
    8088    }
    8189
    82     {
    83         psDB *dbh = psDBInit(HOST, USER, PASSWD, DBNAME, PORT);
     90    if (1) {
     91        psDB *dbh = psDBInit(HOST, USER, PASSWD, DBNAME, PORT);
     92        ok(dbh, "re-open a database handle");
     93
    8494        psMetadata *md = psMetadataAlloc();
    8595        psMetadataAdd(md, PS_LIST_TAIL, "foo", PS_TYPE_S32, "Primary Key", 0);
    86         psDBCreateTable(dbh, "bar", md);
     96        ok(psDBCreateTable(dbh, "bar", md), "psDBCreateTable()");
    8797
    8898        ok(!psDBCreateTable(dbh, "bar", md), "psDBCreateTable() - table already exists");
     
    90100        psFree(md);
    91101
    92         psDBDropTable(dbh, "bar");
     102        ok(psDBDropTable(dbh, "bar"), "psDBDropTable()");
    93103
    94104        ok(!psDBDropTable(dbh, "fubar"), "psDBDropTable() - non-existant table");
     
    96106    }
    97107
    98     {
    99         psDB *dbh = psDBInit(HOST, USER, PASSWD, DBNAME, PORT);
     108    if (1) {
     109        psDB *dbh = psDBInit(HOST, USER, PASSWD, DBNAME, PORT);
     110        ok(dbh, "re-open a database handle");
    100111
    101112        // setup yak table for later tests
     
    103114            psMetadata *md = psMetadataAlloc();
    104115            psMetadataAdd(md, PS_LIST_TAIL, "hair", PS_TYPE_F32, NULL, 0.0);
    105             psDBCreateTable(dbh, "yak", md);
     116            ok(psDBCreateTable(dbh, "yak", md), "psDBCreateTable");
    106117            psFree(md);
    107118        }
     
    111122            psMetadata *md = psMetadataAlloc();
    112123            psMetadataAdd(md, PS_LIST_TAIL, "color", PS_DATA_STRING, NULL, "100");
    113             psDBCreateTable(dbh, "horse", md);
     124            ok(psDBCreateTable(dbh, "horse", md), "psDBCreateTable");
    114125            psFree(md);
    115126        }
    116127
    117128        // psDBInsertOneRow()
    118         {
     129        if (1) {
    119130            psMetadata *md = psMetadataAlloc();
    120131            psMetadataAdd(md, PS_LIST_TAIL, "hair", PS_TYPE_F32, NULL, 10e3);
     
    125136        }
    126137
    127         {
     138        if (1) {
    128139            psMetadata *md = psMetadataAlloc();
    129140            psMetadataAdd(md, PS_LIST_TAIL, "hair", PS_TYPE_F32, NULL, NAN);
     
    156167        }
    157168
     169        // XXX bad
     170
    158171        // psDBSelectColumn()
    159172        {
     
    161174            ok(column, "psDBSelectColumn() - select");
    162175            is_long(psArrayLength(column), 3, "psDBSelectColumn() - number of elements");
     176
     177            // XXX
     178            // exit (2);
    163179
    164180            // XXX this test is depending on the order the rows come out it...
     
    253269
    254270        // psDBDeleteRows()
    255         ok(psDBDeleteRows(dbh, "yak", NULL, 0), "psDBDeleteRows()");
     271        // Note: psDBDeleteRows without a WHERE clause is converted to TRUNCATE TABLE
     272        // name.  This query deletes the table rows but does not return a count of the
     273        // deleted rows.  Thus this returns a 0, not a positive integer.  On failure,
     274        // psDBDeleteRows returns -1 (0 rows can be a valid result)
     275
     276        ok(psDBDeleteRows(dbh, "yak", NULL, 1) == 1, "psDBDeleteRows()");
     277        ok(psDBDeleteRows(dbh, "yak", NULL, 0) == 0, "psDBDeleteRows()");
    256278
    257279        // cleanup other tests
    258         psDBDropTable(dbh, "horse");
    259         psDBDropTable(dbh, "yak");
    260 
    261         psFree(dbh);
    262     }
    263 
     280        ok(psDBDropTable(dbh, "horse"), "psDBDropTable");
     281        ok(psDBDropTable(dbh, "yak"),   "psDBDropTable");
     282
     283        ok(psDBFreeQueryPrepared(), "psDBFreeQueryPrepared()");
     284        psFree(dbh);
     285    }
     286
     287    // Tests of TIME-related types
     288    {
     289        psDB *dbh = psDBInit(HOST, USER, PASSWD, DBNAME, PORT);
     290        ok(dbh, "re-open a database handle");
     291
     292        // create t1 table for time tets
     293        if (1) {
     294            psMetadata *md = psMetadataAlloc();
     295            psMetadataAdd(md, PS_LIST_TAIL, "speed", PS_DATA_F32,  NULL, 0.0);  // dummy column speed
     296            psMetadataAdd(md, PS_LIST_TAIL, "epoch", PS_DATA_TIME, NULL, NULL); // time-type column
     297            ok(psDBCreateTable(dbh, "t1", md), "psDBCreateTable");
     298            psFree(md);
     299        }
     300
     301        {
     302            psMetadata *md = psMetadataAlloc();
     303
     304            psTime *T1 = psTimeGetNow(PS_TIME_TAI);
     305            psMetadataAdd(md, PS_LIST_TAIL, "epoch", PS_DATA_TIME, NULL, T1);
     306            psMetadataAdd(md, PS_LIST_TAIL, "speed", PS_DATA_F32,  NULL, 1.0);
     307            psFree(T1);
     308
     309            ok(psDBInsertOneRow(dbh, "t1", md),"psDBInsertOneRow()");
     310            psFree(md);
     311        }
     312
     313        // psDBInsertRows()
     314        {
     315            psArray *rowSet = psArrayAllocEmpty(3);
     316
     317            psMetadata *R1 = psMetadataAlloc();
     318            psTime *T1 = psTimeGetNow(PS_TIME_TAI);
     319            psMetadataAdd(R1, PS_LIST_TAIL, "speed", PS_DATA_F32,  NULL, 2.0);
     320            psMetadataAdd(R1, PS_LIST_TAIL, "epoch", PS_DATA_TIME, NULL, T1);
     321            psArrayAdd(rowSet, 0, R1);
     322            psFree(T1);
     323            psFree(R1);
     324
     325            psMetadata *R2 = psMetadataAlloc();
     326            psTime *T2 = psTimeFromISO("2026-04-15T00:00:00.0", PS_TIME_TAI);
     327            psMetadataAdd(R2, PS_LIST_TAIL, "speed", PS_DATA_F32,  NULL, 3.0);
     328            psMetadataAdd(R2, PS_LIST_TAIL, "epoch", PS_DATA_TIME, NULL, T2);
     329            psArrayAdd(rowSet, 0, R2);
     330            psFree(T2);
     331            psFree(R2);
     332
     333            ok(psDBInsertRows(dbh, "t1", rowSet), "psDBInsertRows() - multi-row insert");
     334
     335            psFree(rowSet);
     336        }
     337
     338        // empty the database after tests are done
     339        ok(psDBDropTable(dbh, "t1"), "psDBDropTable() - drop table");
     340
     341        ok(psDBFreeQueryPrepared(), "psDBFreeQueryPrepared()");
     342        psFree(dbh);
     343    }
    264344
    265345    done();
Note: See TracChangeset for help on using the changeset viewer.