IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jun 6, 2006, 5:40:43 PM (20 years ago)
Author:
Paul Price
Message:

Applying patch from Josh to break up existing function.

File:
1 edited

Legend:

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

    r7383 r7386  
    1212 *  @author Joshua Hoblitt
    1313 *
    14  *  @version $Revision: 1.55 $ $Name: not supported by cvs2svn $
    15  *  @date $Date: 2006-06-07 03:30:45 $
     14 *  @version $Revision: 1.56 $ $Name: not supported by cvs2svn $
     15 *  @date $Date: 2006-06-07 03:40:43 $
    1616 *
    1717 *  Copyright 2005 Joshua Hoblitt, University of Hawaii
     
    469469                        unsigned long long limit)
    470470{
     471    // Create select row query
     472    char *query = psDBGenerateSelectRowSQL(tableName, NULL, where, limit);
     473    if (!query) {
     474        psError(PS_ERR_UNEXPECTED_NULL, false, "Query generation failed.");
     475        return NULL;
     476    }
     477
     478    // Run SQL query
     479    if (!p_psDBRunQuery(dbh, query)) {
     480        psError(PS_ERR_UNKNOWN, false, "Query execution failed.");
     481        psFree(query);
     482        return NULL;
     483    }
     484    psFree(query);
     485
     486    // return the result
     487    return p_psDBFetchResult(dbh);
     488}
     489
     490bool psDBInsertOneRow(psDB *dbh,
     491                      const char *tableName,
     492                      const psMetadata *row)
     493{
     494    psArray         *rowSet;           // psArray of row to insert
     495
     496    // Check for null row
     497    if(row == NULL) {
     498        psError(PS_ERR_UNKNOWN,true,PS_ERRORTEXT_psDB_INSERT_ROW_FAIL);
     499        return false;
     500    }
     501
     502    // Create array to store single row
     503    rowSet = psArrayAlloc(1);
     504    rowSet->n = 0;
     505    psArrayAdd(rowSet, 0, (psPtr)row);
     506
     507    // Execute function to insert rows
     508    if (!psDBInsertRows(dbh, tableName, rowSet)) {
     509        psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psDB_INSERT_ROW_FAIL);
     510        psFree(rowSet);
     511        return false;
     512    }
     513
     514    psFree(rowSet);
     515
     516    return true;
     517}
     518
     519bool psDBInsertRows(psDB *dbh,
     520                    const char *tableName,
     521                    const psArray *rowSet)
     522{
     523    psMetadata      *row;               // row of data
     524    char            *query;             // SQL query
     525    MYSQL_STMT      *stmt;              // prepared db statement
     526    MYSQL_BIND      *bind;              // field values to insert
     527    unsigned long   paramCount;         // number of placeholders in query
     528    psU64           j;                  // row index
     529
     530    // Verify database connections is set up
     531    if(dbh == NULL) {
     532        psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_INVALID_PSDB);
     533        return false;
     534    }
     535
     536    // Verify row array is non-NULL
     537    if(rowSet == NULL) {
     538        psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_INSERT_ROW_FAIL);
     539        return false;
     540    }
     541
     542    // we are assuming that all rows in the set have an identical with reguard
     543    // to field count and type
     544    row = rowSet->data[0];
     545
     546    // Generate SQL query string
     547    query = psDBGenerateInsertRowSQL(tableName, row);
     548    if (!query) {
     549        psError(PS_ERR_UNEXPECTED_NULL, false, PS_ERRORTEXT_psDB_QUERY_GEN_FAIL);
     550        return false;
     551    }
     552
     553    // Prepare SQL statement
     554    stmt = mysql_stmt_init(dbh->mysql);
     555    if (!stmt) {
     556        psAbort(__func__, "mysql_stmt_init(), out of memory.");
     557    }
     558    if (mysql_stmt_prepare(stmt, query, (unsigned long)strlen(query))) {
     559        psError(PS_ERR_UNKNOWN, true, "Failed to prepare query.  Error: %s", mysql_stmt_error(stmt));
     560        mysql_stmt_close(stmt);
     561        psFree(query);
     562        return false;
     563    }
     564
     565    psFree(query);
     566
     567    // how many place holders are in our query
     568    paramCount = mysql_stmt_param_count(stmt);
     569
     570    // structure larger enough to hold one field of data per place holder
     571    bind = psAlloc(sizeof(MYSQL_BIND) * paramCount);
     572
     573    // loop over rows
     574    for (j = 0; j < rowSet->n; j++) {
     575        row = rowSet->data[j];
     576
     577        // reset bind for each row
     578        memset(bind, 0, sizeof(MYSQL_BIND) * paramCount);
     579
     580        if (!psDBPackRow(bind, row, paramCount)) {
     581            psError(PS_ERR_UNKNOWN, false, "Failed to pack params into bind structure.");
     582
     583            mysql_rollback(dbh->mysql);
     584
     585            psFree(bind);
     586            mysql_stmt_close(stmt);
     587        }
     588
     589        if (mysql_stmt_bind_param(stmt, bind)) {
     590            psError(PS_ERR_UNKNOWN, true, "Failed to bind params.  Error: %s", mysql_stmt_error(stmt));
     591
     592            mysql_rollback(dbh->mysql);
     593
     594            psFree(bind);
     595            mysql_stmt_close(stmt);
     596
     597            return false;
     598        }
     599
     600        if (mysql_stmt_execute(stmt)) {
     601            psError(PS_ERR_UNKNOWN, true, "Failed to execute prepared statement.  Error: %s",
     602                    mysql_stmt_error(stmt));
     603
     604            mysql_rollback(dbh->mysql);
     605
     606            psFree(bind);
     607            mysql_stmt_close(stmt);
     608
     609            return false;
     610        }
     611    } // end loop over rows
     612
     613    psFree(bind);
     614    mysql_stmt_close(stmt);
     615
     616    return true;
     617}
     618
     619psArray *psDBDumpRows(psDB *dbh,
     620                      const char *tableName)
     621{
     622    return psDBSelectRows(dbh, tableName, NULL, 0);
     623}
     624
     625psMetadata *psDBDumpCols(psDB *dbh,
     626                         const char *tableName)
     627{
     628    MYSQL_RES       *result;
     629    MYSQL_FIELD     *field;
     630    unsigned int    fieldCount;
     631    psMetadata      *table;
     632    psU32           pType;
     633    unsigned int    i;
     634    psPtr           column;
     635
     636    // Verify database object is not null
     637    if(dbh == NULL) {
     638        psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_INVALID_PSDB);
     639        return NULL;
     640    }
     641
     642    // Verify table name is not null
     643    if(tableName == NULL) {
     644        psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_NULL_TABLE);
     645        return NULL;
     646    }
     647
     648    // find column types
     649    result = mysql_list_fields(dbh->mysql, tableName, NULL);
     650    if (!result) {
     651        psError(PS_ERR_UNEXPECTED_NULL, true, "Failed to retrieve column types.");
     652    }
     653
     654    field = mysql_fetch_fields(result);
     655    fieldCount = mysql_num_fields(result);
     656
     657    table = psMetadataAlloc();
     658
     659    // fetch each column and load into psMetadata
     660    for (i =0; i < fieldCount; i++) {
     661        // find ptype of column
     662        pType = psDBMySQLToPType(field[i].type, field[i].flags);
     663        //psLogMsg( __func__, PS_LOG_INFO, "pType=[%ld]\n", pType );
     664
     665        // if the ptype is PS_TYPE_PTR assume that it's a string and fetch the
     666        // column as an psArray of strings; otherwise fetch the column as a
     667        // psVector.
     668        if (pType == PS_DATA_STRING) {
     669            // PS_DATA_UNKNOWN -> PS_DATA_ARRAY ?
     670            column = psDBSelectColumn(dbh, tableName, field[i].name, 0);
     671            psMetadataAddArray(table, PS_LIST_TAIL, field[i].name, 0, "", column);
     672            //            psMetadataAddStr(table, PS_LIST_TAIL, field[i].name, "", column);
     673            psFree(column);
     674        } else {
     675            column = psDBSelectColumnNum(dbh, tableName, field[i].name, pType, 0);
     676            psMetadataAddVector(table, PS_LIST_TAIL, field[i].name, 0, "", column);
     677            psFree(column);
     678        }
     679    }
     680
     681    return table;
     682}
     683
     684long psDBUpdateRows(psDB *dbh,
     685                    const char *tableName,
     686                    const psMetadata *where,
     687                    const psMetadata *values)
     688{
     689    char            *query;
     690    MYSQL_STMT      *stmt;              // prepared db statement
     691    unsigned long   paramCount;         // number of placeholders in query
     692    MYSQL_BIND      *bind;              // field values to insert
     693    my_ulonglong    rowsAffected;       // number of rows affected by query
     694
     695    // Verify database object is not NULL
     696    if(dbh == NULL) {
     697        psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_INVALID_PSDB);
     698        return -1;
     699    }
     700
     701    // Generate SQL query to update row
     702    query = psDBGenerateUpdateRowSQL(tableName, where, values);
     703    if (!query) {
     704        psError(PS_ERR_UNEXPECTED_NULL, false, PS_ERRORTEXT_psDB_QUERY_GEN_FAIL);
     705        return -1;
     706    }
     707
     708    // Initialize SQL statement
     709    stmt = mysql_stmt_init(dbh->mysql);
     710    if (!stmt) {
     711        psAbort(__func__, "mysql_stmt_init(), out of memory.");
     712    }
     713
     714    // Prepare SQL statement
     715    if (mysql_stmt_prepare(stmt, query, (unsigned long)strlen(query))) {
     716        psError(PS_ERR_UNKNOWN, true, PS_ERRORTEXT_psDB_SQL_PREPARE_FAIL, mysql_stmt_error(stmt));
     717        mysql_stmt_close(stmt);
     718        psFree(query);
     719        return -1;
     720    }
     721    psFree(query);
     722
     723    // how many place holders are in our query
     724    paramCount = mysql_stmt_param_count(stmt);
     725
     726    // structure large enough to hold one field of data per place holder
     727    bind = psAlloc(sizeof(MYSQL_BIND) * paramCount);
     728
     729    // init bind
     730    memset(bind, 0, sizeof(MYSQL_BIND) * paramCount);
     731
     732    if (!psDBPackRow(bind, values, paramCount)) {
     733        psFree(bind);
     734        mysql_stmt_close(stmt);
     735        return -1;
     736    }
     737
     738    if (mysql_stmt_bind_param(stmt, bind)) {
     739        psError(PS_ERR_UNKNOWN, true, "Failed to bind params.  Error: %s", mysql_stmt_error(stmt));
     740        mysql_rollback(dbh->mysql);
     741        psFree(bind);
     742        mysql_stmt_close(stmt);
     743        return -1;
     744    }
     745
     746    if (mysql_stmt_execute(stmt)) {
     747        psError(PS_ERR_UNKNOWN, true, "Failed to execute prepared statement.  Error: %s",
     748                mysql_stmt_error(stmt));
     749        mysql_rollback(dbh->mysql);
     750        psFree(bind);
     751        mysql_stmt_close(stmt);
     752        return -1;
     753    }
     754
     755    psFree(bind);
     756
     757    // mysql_stmt_affected_rows() must be called before a commit
     758    rowsAffected = mysql_stmt_affected_rows(stmt);
     759
     760    mysql_stmt_close(stmt);
     761
     762    return rowsAffected;
     763}
     764
     765long psDBDeleteRows(psDB *dbh,
     766                    const char *tableName,
     767                    const psMetadata *where,
     768                    unsigned long long limit)
     769{
     770    char            *query;
     771    psS64           rows = 0;
     772
     773    // Verify database is not NULL
     774    if(dbh == NULL) {
     775        psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
     776        return -1;
     777    }
     778
     779    // Create SQL statement string
     780    query = psDBGenerateDeleteRowSQL(tableName, where,limit);
     781    if (!query) {
     782        psError(PS_ERR_UNEXPECTED_NULL, false, "Query generation failed.");
     783        return -1;
     784    }
     785
     786    // Run SQL query
     787    if (!p_psDBRunQuery(dbh, query)) {
     788        psError(PS_ERR_UNKNOWN, false, "Delete failed.");
     789        mysql_rollback(dbh->mysql);
     790        psFree(query);
     791        return -1;
     792    }
     793    psFree(query);
     794
     795    // Get the number of affected row for the delete command
     796    rows = (psS64)mysql_affected_rows(dbh->mysql);
     797
     798    return rows;
     799}
     800
     801long psDBLastInsertID(psDB *dbh)
     802{
     803    // XXX return type is actually my_ulonglong - should the return be psU64?
     804    return (long)mysql_insert_id(dbh->mysql);
     805}
     806
     807bool psDBExplicitTrans(psDB *dbh, bool mode)
     808{
     809    // Verify database is not NULL
     810    if(dbh == NULL) {
     811        psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
     812        return false;
     813    }
     814
     815    // mode needs to be inverted as autocommits are the opposide of explicit
     816    // transactions.
     817    // the return value also needs to be inverted for the same reason.
     818    // is it safe to assume my_bool always safely casts to bool?
     819    return !(bool)mysql_autocommit(dbh->mysql, !mode);
     820}
     821
     822bool psDBTransaction(psDB *dbh)
     823{
     824    // Verify database is not NULL
     825    if(dbh == NULL) {
     826        psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
     827        return false;
     828    }
     829
     830    bool status = p_psDBRunQuery(dbh, "START TRANSACTION");
     831    if (!status) {
     832        psError(PS_ERR_UNKNOWN, false, "Failed to start a new transaction.");
     833    }
     834
     835    return status;
     836}
     837
     838bool psDBCommit(psDB *dbh)
     839{
     840    // Verify database is not NULL
     841    if(dbh == NULL) {
     842        psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
     843        return false;
     844    }
     845
     846    // is it safe to assume my_bool always safely casts to bool?
     847    // mysql_commit - Zero if successful. Non-zero if an error occurred.
     848    return !(bool)mysql_commit(dbh->mysql);
     849}
     850
     851bool psDBRollback(psDB *dbh)
     852{
     853    // Verify database is not NULL
     854    if(dbh == NULL) {
     855        psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
     856        return false;
     857    }
     858
     859    // is it safe to assume my_bool always safely casts to bool?
     860    // mysql_rollback - Zero if successful. Non-zero if an error occurred.
     861    return !(bool)mysql_rollback(dbh->mysql);
     862}
     863
     864
     865// database utility functions
     866/*****************************************************************************/
     867
     868bool p_psDBRunQuery(psDB *dbh,
     869                    const char *format,
     870                    ...)
     871{
     872    va_list argPtr;
     873    char *dest = NULL;
     874
     875    // Verify database object is not NULL
     876    if(dbh == NULL) {
     877        psError(PS_ERR_BAD_PARAMETER_NULL,true,PS_ERRORTEXT_psDB_INVALID_PSDB);
     878        return false;
     879    }
     880
     881    // Run query
     882    va_start(argPtr, format);
     883    if(argPtr == NULL) {
     884        dest=psStringCopy(format);
     885    } else {
     886        int destSize = vsnprintf(dest, 0, format, argPtr);
     887        dest = psAlloc(destSize+1);
     888        vsnprintf(dest, destSize+1, format, argPtr);
     889    }
     890    va_end(argPtr);
     891    if (mysql_real_query(dbh->mysql, dest, (unsigned long)strlen(dest)) !=0) {
     892        //The following if statement was added to standardize outputs between platforms for testing purposes.
     893        char mysqlTemp[165];
     894        strncpy(mysqlTemp,
     895                "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'null) WHERE' at line 1", 165);
     896        if ( !strncmp(mysql_error(dbh->mysql), mysqlTemp, 145) ) {
     897            psError(PS_ERR_UNKNOWN, true, PS_ERRORTEXT_psDB_SQL_QUERY_FAIL, mysqlTemp);
     898        } else {
     899            psError(PS_ERR_UNKNOWN, true, PS_ERRORTEXT_psDB_SQL_QUERY_FAIL, mysql_error(dbh->mysql));
     900        }
     901        psFree(dest);
     902        return false;
     903    }
     904
     905    psFree(dest);
     906    return true;
     907}
     908
     909psArray *p_psDBSFetchResult(psDB *dbh)
     910{
    471911    MYSQL_RES       *result;            // complete db result set
    472912    MYSQL_ROW       row;                // single row of db result set
    473913    MYSQL_FIELD     *field;             // field type info
    474     char            *query;             // SQL query
    475914    my_ulonglong    rowCount;           // number of rows in db result set
    476915    unsigned int    fieldCount;         // number of fields in db result set
     
    482921    psU32           pType;              // psElemType of a field
    483922    psPtr           data;               // copy of result field
    484 
    485     // Create select row query
    486     query = psDBGenerateSelectRowSQL(tableName, NULL, where, limit);
    487     if (!query) {
    488         psError(PS_ERR_UNEXPECTED_NULL, false, "Query generation failed.");
    489         return NULL;
    490     }
    491 
    492     // Run SQL query
    493     if (!p_psDBRunQuery(dbh, query)) {
    494         psError(PS_ERR_UNKNOWN, false, "Query execution failed.");
    495         psFree(query);
    496         return NULL;
    497     }
    498     psFree(query);
    499923
    500924    result = mysql_store_result(dbh->mysql);
     
    575999
    5761000    return resultSet;
    577 }
    578 
    579 bool psDBInsertOneRow(psDB *dbh,
    580                       const char *tableName,
    581                       const psMetadata *row)
    582 {
    583     psArray         *rowSet;           // psArray of row to insert
    584 
    585     // Check for null row
    586     if(row == NULL) {
    587         psError(PS_ERR_UNKNOWN,true,PS_ERRORTEXT_psDB_INSERT_ROW_FAIL);
    588         return false;
    589     }
    590 
    591     // Create array to store single row
    592     rowSet = psArrayAlloc(1);
    593     rowSet->n = 0;
    594     psArrayAdd(rowSet, 0, (psPtr)row);
    595 
    596     // Execute function to insert rows
    597     if (!psDBInsertRows(dbh, tableName, rowSet)) {
    598         psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psDB_INSERT_ROW_FAIL);
    599         psFree(rowSet);
    600         return false;
    601     }
    602 
    603     psFree(rowSet);
    604 
    605     return true;
    606 }
    607 
    608 bool psDBInsertRows(psDB *dbh,
    609                     const char *tableName,
    610                     const psArray *rowSet)
    611 {
    612     psMetadata      *row;               // row of data
    613     char            *query;             // SQL query
    614     MYSQL_STMT      *stmt;              // prepared db statement
    615     MYSQL_BIND      *bind;              // field values to insert
    616     unsigned long   paramCount;         // number of placeholders in query
    617     psU64           j;                  // row index
    618 
    619     // Verify database connections is set up
    620     if(dbh == NULL) {
    621         psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_INVALID_PSDB);
    622         return false;
    623     }
    624 
    625     // Verify row array is non-NULL
    626     if(rowSet == NULL) {
    627         psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_INSERT_ROW_FAIL);
    628         return false;
    629     }
    630 
    631     // we are assuming that all rows in the set have an identical with reguard
    632     // to field count and type
    633     row = rowSet->data[0];
    634 
    635     // Generate SQL query string
    636     query = psDBGenerateInsertRowSQL(tableName, row);
    637     if (!query) {
    638         psError(PS_ERR_UNEXPECTED_NULL, false, PS_ERRORTEXT_psDB_QUERY_GEN_FAIL);
    639         return false;
    640     }
    641 
    642     // Prepare SQL statement
    643     stmt = mysql_stmt_init(dbh->mysql);
    644     if (!stmt) {
    645         psAbort(__func__, "mysql_stmt_init(), out of memory.");
    646     }
    647     if (mysql_stmt_prepare(stmt, query, (unsigned long)strlen(query))) {
    648         psError(PS_ERR_UNKNOWN, true, "Failed to prepare query.  Error: %s", mysql_stmt_error(stmt));
    649         mysql_stmt_close(stmt);
    650         psFree(query);
    651         return false;
    652     }
    653 
    654     psFree(query);
    655 
    656     // how many place holders are in our query
    657     paramCount = mysql_stmt_param_count(stmt);
    658 
    659     // structure larger enough to hold one field of data per place holder
    660     bind = psAlloc(sizeof(MYSQL_BIND) * paramCount);
    661 
    662     // loop over rows
    663     for (j = 0; j < rowSet->n; j++) {
    664         row = rowSet->data[j];
    665 
    666         // reset bind for each row
    667         memset(bind, 0, sizeof(MYSQL_BIND) * paramCount);
    668 
    669         if (!psDBPackRow(bind, row, paramCount)) {
    670             psError(PS_ERR_UNKNOWN, false, "Failed to pack params into bind structure.");
    671 
    672             mysql_rollback(dbh->mysql);
    673 
    674             psFree(bind);
    675             mysql_stmt_close(stmt);
    676         }
    677 
    678         if (mysql_stmt_bind_param(stmt, bind)) {
    679             psError(PS_ERR_UNKNOWN, true, "Failed to bind params.  Error: %s", mysql_stmt_error(stmt));
    680 
    681             mysql_rollback(dbh->mysql);
    682 
    683             psFree(bind);
    684             mysql_stmt_close(stmt);
    685 
    686             return false;
    687         }
    688 
    689         if (mysql_stmt_execute(stmt)) {
    690             psError(PS_ERR_UNKNOWN, true, "Failed to execute prepared statement.  Error: %s",
    691                     mysql_stmt_error(stmt));
    692 
    693             mysql_rollback(dbh->mysql);
    694 
    695             psFree(bind);
    696             mysql_stmt_close(stmt);
    697 
    698             return false;
    699         }
    700     } // end loop over rows
    701 
    702     psFree(bind);
    703     mysql_stmt_close(stmt);
    704 
    705     return true;
    706 }
    707 
    708 psArray *psDBDumpRows(psDB *dbh,
    709                       const char *tableName)
    710 {
    711     return psDBSelectRows(dbh, tableName, NULL, 0);
    712 }
    713 
    714 psMetadata *psDBDumpCols(psDB *dbh,
    715                          const char *tableName)
    716 {
    717     MYSQL_RES       *result;
    718     MYSQL_FIELD     *field;
    719     unsigned int    fieldCount;
    720     psMetadata      *table;
    721     psU32           pType;
    722     unsigned int    i;
    723     psPtr           column;
    724 
    725     // Verify database object is not null
    726     if(dbh == NULL) {
    727         psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_INVALID_PSDB);
    728         return NULL;
    729     }
    730 
    731     // Verify table name is not null
    732     if(tableName == NULL) {
    733         psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_NULL_TABLE);
    734         return NULL;
    735     }
    736 
    737     // find column types
    738     result = mysql_list_fields(dbh->mysql, tableName, NULL);
    739     if (!result) {
    740         psError(PS_ERR_UNEXPECTED_NULL, true, "Failed to retrieve column types.");
    741     }
    742 
    743     field = mysql_fetch_fields(result);
    744     fieldCount = mysql_num_fields(result);
    745 
    746     table = psMetadataAlloc();
    747 
    748     // fetch each column and load into psMetadata
    749     for (i =0; i < fieldCount; i++) {
    750         // find ptype of column
    751         pType = psDBMySQLToPType(field[i].type, field[i].flags);
    752         //psLogMsg( __func__, PS_LOG_INFO, "pType=[%ld]\n", pType );
    753 
    754         // if the ptype is PS_TYPE_PTR assume that it's a string and fetch the
    755         // column as an psArray of strings; otherwise fetch the column as a
    756         // psVector.
    757         if (pType == PS_DATA_STRING) {
    758             // PS_DATA_UNKNOWN -> PS_DATA_ARRAY ?
    759             column = psDBSelectColumn(dbh, tableName, field[i].name, 0);
    760             psMetadataAddArray(table, PS_LIST_TAIL, field[i].name, 0, "", column);
    761             //            psMetadataAddStr(table, PS_LIST_TAIL, field[i].name, "", column);
    762             psFree(column);
    763         } else {
    764             column = psDBSelectColumnNum(dbh, tableName, field[i].name, pType, 0);
    765             psMetadataAddVector(table, PS_LIST_TAIL, field[i].name, 0, "", column);
    766             psFree(column);
    767         }
    768     }
    769 
    770     return table;
    771 }
    772 
    773 long psDBUpdateRows(psDB *dbh,
    774                     const char *tableName,
    775                     const psMetadata *where,
    776                     const psMetadata *values)
    777 {
    778     char            *query;
    779     MYSQL_STMT      *stmt;              // prepared db statement
    780     unsigned long   paramCount;         // number of placeholders in query
    781     MYSQL_BIND      *bind;              // field values to insert
    782     my_ulonglong    rowsAffected;       // number of rows affected by query
    783 
    784     // Verify database object is not NULL
    785     if(dbh == NULL) {
    786         psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_INVALID_PSDB);
    787         return -1;
    788     }
    789 
    790     // Generate SQL query to update row
    791     query = psDBGenerateUpdateRowSQL(tableName, where, values);
    792     if (!query) {
    793         psError(PS_ERR_UNEXPECTED_NULL, false, PS_ERRORTEXT_psDB_QUERY_GEN_FAIL);
    794         return -1;
    795     }
    796 
    797     // Initialize SQL statement
    798     stmt = mysql_stmt_init(dbh->mysql);
    799     if (!stmt) {
    800         psAbort(__func__, "mysql_stmt_init(), out of memory.");
    801     }
    802 
    803     // Prepare SQL statement
    804     if (mysql_stmt_prepare(stmt, query, (unsigned long)strlen(query))) {
    805         psError(PS_ERR_UNKNOWN, true, PS_ERRORTEXT_psDB_SQL_PREPARE_FAIL, mysql_stmt_error(stmt));
    806         mysql_stmt_close(stmt);
    807         psFree(query);
    808         return -1;
    809     }
    810     psFree(query);
    811 
    812     // how many place holders are in our query
    813     paramCount = mysql_stmt_param_count(stmt);
    814 
    815     // structure large enough to hold one field of data per place holder
    816     bind = psAlloc(sizeof(MYSQL_BIND) * paramCount);
    817 
    818     // init bind
    819     memset(bind, 0, sizeof(MYSQL_BIND) * paramCount);
    820 
    821     if (!psDBPackRow(bind, values, paramCount)) {
    822         psFree(bind);
    823         mysql_stmt_close(stmt);
    824         return -1;
    825     }
    826 
    827     if (mysql_stmt_bind_param(stmt, bind)) {
    828         psError(PS_ERR_UNKNOWN, true, "Failed to bind params.  Error: %s", mysql_stmt_error(stmt));
    829         mysql_rollback(dbh->mysql);
    830         psFree(bind);
    831         mysql_stmt_close(stmt);
    832         return -1;
    833     }
    834 
    835     if (mysql_stmt_execute(stmt)) {
    836         psError(PS_ERR_UNKNOWN, true, "Failed to execute prepared statement.  Error: %s",
    837                 mysql_stmt_error(stmt));
    838         mysql_rollback(dbh->mysql);
    839         psFree(bind);
    840         mysql_stmt_close(stmt);
    841         return -1;
    842     }
    843 
    844     psFree(bind);
    845 
    846     // mysql_stmt_affected_rows() must be called before a commit
    847     rowsAffected = mysql_stmt_affected_rows(stmt);
    848 
    849     mysql_stmt_close(stmt);
    850 
    851     return rowsAffected;
    852 }
    853 
    854 long psDBDeleteRows(psDB *dbh,
    855                     const char *tableName,
    856                     const psMetadata *where,
    857                     unsigned long long limit)
    858 {
    859     char            *query;
    860     psS64           rows = 0;
    861 
    862     // Verify database is not NULL
    863     if(dbh == NULL) {
    864         psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
    865         return -1;
    866     }
    867 
    868     // Create SQL statement string
    869     query = psDBGenerateDeleteRowSQL(tableName, where,limit);
    870     if (!query) {
    871         psError(PS_ERR_UNEXPECTED_NULL, false, "Query generation failed.");
    872         return -1;
    873     }
    874 
    875     // Run SQL query
    876     if (!p_psDBRunQuery(dbh, query)) {
    877         psError(PS_ERR_UNKNOWN, false, "Delete failed.");
    878         mysql_rollback(dbh->mysql);
    879         psFree(query);
    880         return -1;
    881     }
    882     psFree(query);
    883 
    884     // Get the number of affected row for the delete command
    885     rows = (psS64)mysql_affected_rows(dbh->mysql);
    886 
    887     return rows;
    888 }
    889 
    890 long psDBLastInsertID(psDB *dbh)
    891 {
    892     // XXX return type is actually my_ulonglong - should the return be psU64?
    893     return (long)mysql_insert_id(dbh->mysql);
    894 }
    895 
    896 bool psDBExplicitTrans(psDB *dbh, bool mode)
    897 {
    898     // Verify database is not NULL
    899     if(dbh == NULL) {
    900         psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
    901         return false;
    902     }
    903 
    904     // mode needs to be inverted as autocommits are the opposide of explicit
    905     // transactions.
    906     // the return value also needs to be inverted for the same reason.
    907     // is it safe to assume my_bool always safely casts to bool?
    908     return !(bool)mysql_autocommit(dbh->mysql, !mode);
    909 }
    910 
    911 bool psDBTransaction(psDB *dbh)
    912 {
    913     // Verify database is not NULL
    914     if(dbh == NULL) {
    915         psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
    916         return false;
    917     }
    918 
    919     bool status = p_psDBRunQuery(dbh, "START TRANSACTION");
    920     if (!status) {
    921         psError(PS_ERR_UNKNOWN, false, "Failed to start a new transaction.");
    922     }
    923 
    924     return status;
    925 }
    926 
    927 bool psDBCommit(psDB *dbh)
    928 {
    929     // Verify database is not NULL
    930     if(dbh == NULL) {
    931         psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
    932         return false;
    933     }
    934 
    935     // is it safe to assume my_bool always safely casts to bool?
    936     // mysql_commit - Zero if successful. Non-zero if an error occurred.
    937     return !(bool)mysql_commit(dbh->mysql);
    938 }
    939 
    940 bool psDBRollback(psDB *dbh)
    941 {
    942     // Verify database is not NULL
    943     if(dbh == NULL) {
    944         psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
    945         return false;
    946     }
    947 
    948     // is it safe to assume my_bool always safely casts to bool?
    949     // mysql_rollback - Zero if successful. Non-zero if an error occurred.
    950     return !(bool)mysql_rollback(dbh->mysql);
    951 }
    952 
    953 
    954 // database utility functions
    955 /*****************************************************************************/
    956 
    957 bool p_psDBRunQuery(psDB *dbh,
    958                     const char *format,
    959                     ...)
    960 {
    961     va_list argPtr;
    962     char *dest = NULL;
    963 
    964     // Verify database object is not NULL
    965     if(dbh == NULL) {
    966         psError(PS_ERR_BAD_PARAMETER_NULL,true,PS_ERRORTEXT_psDB_INVALID_PSDB);
    967         return false;
    968     }
    969 
    970     // Run query
    971     va_start(argPtr, format);
    972     if(argPtr == NULL) {
    973         dest=psStringCopy(format);
    974     } else {
    975         int destSize = vsnprintf(dest, 0, format, argPtr);
    976         dest = psAlloc(destSize+1);
    977         vsnprintf(dest, destSize+1, format, argPtr);
    978     }
    979     va_end(argPtr);
    980     if (mysql_real_query(dbh->mysql, dest, (unsigned long)strlen(dest)) !=0) {
    981         //The following if statement was added to standardize outputs between platforms for testing purposes.
    982         char mysqlTemp[165];
    983         strncpy(mysqlTemp,
    984                 "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'null) WHERE' at line 1", 165);
    985         if ( !strncmp(mysql_error(dbh->mysql), mysqlTemp, 145) ) {
    986             psError(PS_ERR_UNKNOWN, true, PS_ERRORTEXT_psDB_SQL_QUERY_FAIL, mysqlTemp);
    987         } else {
    988             psError(PS_ERR_UNKNOWN, true, PS_ERRORTEXT_psDB_SQL_QUERY_FAIL, mysql_error(dbh->mysql));
    989         }
    990         psFree(dest);
    991         return false;
    992     }
    993 
    994     psFree(dest);
    995     return true;
    9961001}
    9971002
Note: See TracChangeset for help on using the changeset viewer.