Changeset 7386 for trunk/psLib/src/db/psDB.c
- Timestamp:
- Jun 6, 2006, 5:40:43 PM (20 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/db/psDB.c (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/db/psDB.c
r7383 r7386 12 12 * @author Joshua Hoblitt 13 13 * 14 * @version $Revision: 1.5 5$ $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 $ 16 16 * 17 17 * Copyright 2005 Joshua Hoblitt, University of Hawaii … … 469 469 unsigned long long limit) 470 470 { 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 490 bool 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 519 bool 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 619 psArray *psDBDumpRows(psDB *dbh, 620 const char *tableName) 621 { 622 return psDBSelectRows(dbh, tableName, NULL, 0); 623 } 624 625 psMetadata *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 684 long 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 765 long 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 801 long 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 807 bool 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 822 bool 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 838 bool 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 851 bool 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 868 bool 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 909 psArray *p_psDBSFetchResult(psDB *dbh) 910 { 471 911 MYSQL_RES *result; // complete db result set 472 912 MYSQL_ROW row; // single row of db result set 473 913 MYSQL_FIELD *field; // field type info 474 char *query; // SQL query475 914 my_ulonglong rowCount; // number of rows in db result set 476 915 unsigned int fieldCount; // number of fields in db result set … … 482 921 psU32 pType; // psElemType of a field 483 922 psPtr data; // copy of result field 484 485 // Create select row query486 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 query493 if (!p_psDBRunQuery(dbh, query)) {494 psError(PS_ERR_UNKNOWN, false, "Query execution failed.");495 psFree(query);496 return NULL;497 }498 psFree(query);499 923 500 924 result = mysql_store_result(dbh->mysql); … … 575 999 576 1000 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 insert584 585 // Check for null row586 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 row592 rowSet = psArrayAlloc(1);593 rowSet->n = 0;594 psArrayAdd(rowSet, 0, (psPtr)row);595 596 // Execute function to insert rows597 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 data613 char *query; // SQL query614 MYSQL_STMT *stmt; // prepared db statement615 MYSQL_BIND *bind; // field values to insert616 unsigned long paramCount; // number of placeholders in query617 psU64 j; // row index618 619 // Verify database connections is set up620 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-NULL626 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 reguard632 // to field count and type633 row = rowSet->data[0];634 635 // Generate SQL query string636 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 statement643 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 query657 paramCount = mysql_stmt_param_count(stmt);658 659 // structure larger enough to hold one field of data per place holder660 bind = psAlloc(sizeof(MYSQL_BIND) * paramCount);661 662 // loop over rows663 for (j = 0; j < rowSet->n; j++) {664 row = rowSet->data[j];665 666 // reset bind for each row667 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 rows701 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 null726 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 null732 if(tableName == NULL) {733 psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_NULL_TABLE);734 return NULL;735 }736 737 // find column types738 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 psMetadata749 for (i =0; i < fieldCount; i++) {750 // find ptype of column751 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 the755 // column as an psArray of strings; otherwise fetch the column as a756 // 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 statement780 unsigned long paramCount; // number of placeholders in query781 MYSQL_BIND *bind; // field values to insert782 my_ulonglong rowsAffected; // number of rows affected by query783 784 // Verify database object is not NULL785 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 row791 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 statement798 stmt = mysql_stmt_init(dbh->mysql);799 if (!stmt) {800 psAbort(__func__, "mysql_stmt_init(), out of memory.");801 }802 803 // Prepare SQL statement804 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 query813 paramCount = mysql_stmt_param_count(stmt);814 815 // structure large enough to hold one field of data per place holder816 bind = psAlloc(sizeof(MYSQL_BIND) * paramCount);817 818 // init bind819 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 commit847 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 NULL863 if(dbh == NULL) {864 psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);865 return -1;866 }867 868 // Create SQL statement string869 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 query876 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 command885 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 NULL899 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 explicit905 // 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 NULL914 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 NULL930 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 NULL943 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 functions955 /*****************************************************************************/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 NULL965 if(dbh == NULL) {966 psError(PS_ERR_BAD_PARAMETER_NULL,true,PS_ERRORTEXT_psDB_INVALID_PSDB);967 return false;968 }969 970 // Run query971 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;996 1001 } 997 1002
Note:
See TracChangeset
for help on using the changeset viewer.
