Index: trunk/archive/psdb/psDB.c
===================================================================
--- trunk/archive/psdb/psDB.c	(revision 3166)
+++ trunk/archive/psdb/psDB.c	(revision 3175)
@@ -8,6 +8,6 @@
  *  @author Joshua Hoblitt
  *
- *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-02-09 01:15:39 $
+ *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-02-10 00:02:16 $
  *
  *  Copyright 2005 Joshua Hoblitt, University of Hawaii
@@ -25,6 +25,6 @@
 typedef struct
 {
-    psU32   type;
-    bool    isUnsigned;
+    enum enum_field_types type;
+    bool            isUnsigned;
 } mysqlType;
 
@@ -564,4 +564,129 @@
         return false;
     }
+
+    // point of no return
+    mysql_commit(dbh->mysql);
+
+    psFree(bind);
+    mysql_stmt_close(stmt);
+
+    return true;
+}
+
+bool psDBInsertRows(psDB *dbh, const char *tableName, psArray *rowSet)
+{
+    psMetadata      *row;               // row of data
+    char            *query;             // SQL query
+    MYSQL_STMT      *stmt;              // prepared db statement
+    MYSQL_BIND      *bind;              // field values to insert
+    psU32           paramCount;         // number of placeholders in query
+    psHash          *mysqlFieldType;    // type lookup table
+    mysqlType       *mType;             // type tmp variable
+    char            *key;               // hash tmp variable
+    psMetadataItem  *item;              // field in row
+    psListIterator  *cursor;            // row iterator
+    psU32           i;                  // field index
+    psU64           j;                  // row index
+    bool            isNull = true;      // used in a MYSQL_BIND to indicate NULL
+
+    // we are assuming that all rows in the set have an identical with reguard
+    // to field count and type
+    row = rowSet->data[0];
+
+    query = psDBGenerateInsertRowSQL(tableName, row);
+    if (!query) {
+        return NULL;
+    }
+
+    stmt = mysql_stmt_init(dbh->mysql);
+    if (!stmt) {
+        // call abort?
+        fprintf(stderr, " mysql_stmt_init(), out of memory\n");
+
+        return false;
+    }
+
+    if (mysql_stmt_prepare(stmt, query, (unsigned long)strlen(query))) {
+            fprintf(stderr, "Failed to prepare query.  Error: %s\n", mysql_stmt_error(stmt));
+
+            mysql_stmt_close(stmt);
+            psFree(query);
+
+            return false;
+    }
+
+    psFree(query);
+
+    // how many place holders are in our query
+    paramCount = (psU32)mysql_stmt_param_count(stmt);
+
+    // structure larger enough to hold one field of data per place holder
+    bind = psAlloc(sizeof(MYSQL_BIND) * paramCount);
+
+    mysqlFieldType = psDBGetPSToMySQLTable();
+
+    // loop over rows
+    for (j = 0; j < rowSet->n; j++) {
+        cursor = psListIteratorAlloc(row->list, 0);
+
+        // reset bind for each row
+        memset(bind, 0, sizeof(MYSQL_BIND) * paramCount);
+
+        // loop over fields
+        i = 0;
+        while ((item = psListGetNext(cursor))) {
+            key = psDBIntToString((psU64)item->pType);
+            mType = psHashLookup(mysqlFieldType, key);
+            psFree(key);
+
+            // input data length is determined by the MYSQL_TYPE_* unless it's a string
+            bind[i].buffer  = (char *)item->data.V;
+            bind[i].buffer_type = mType->type;
+            bind[i].is_unsigned = mType->isUnsigned;
+
+            // convert NaNs to NULL
+            bind[i].is_null = psDBIsPTypeNaN(item->pType, item->data.V) 
+                            ? (my_bool *)&isNull
+                            : NULL;
+
+            if (item->pType == PS_TYPE_PTR) {
+                if (item->type == PS_META_STR) {
+                    if (*(char *)item->data.V == '\0') {
+                        bind[i].is_null = (my_bool *)&isNull;
+                    } else {
+                        bind[i].buffer_length = (unsigned long)strlen((char *)item->data.V);
+                        bind[i].is_null = NULL;
+                    }
+                } else {
+                    // error, not a pointer to a string
+                }
+            }
+
+            // increment field index
+            i++;
+        }
+
+        psFree(cursor);
+
+        if (mysql_stmt_bind_param(stmt, bind)) {
+            fprintf(stderr, "Failed to bind params.  Error: %s\n", mysql_stmt_error(stmt));
+
+            psFree(bind);
+            mysql_stmt_close(stmt);
+
+            return false;
+        }
+
+        if (mysql_stmt_execute(stmt)) {
+            fprintf(stderr, "Failed to execute prepared statement.  Error: %s\n", mysql_stmt_error(stmt));
+
+            psFree(bind);
+            mysql_stmt_close(stmt);
+
+            return false;
+        }
+    } // end loop over rows
+
+    psFree(mysqlFieldType);
 
     // point of no return
