00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 #include "database_interface/postgresql_database.h"
00038 
00039 
00040 #include <libpq-fe.h>
00041 
00042 #include <sstream>
00043 #include <iostream>
00044 
00045 namespace database_interface {
00046 
00051 class PostgresqlDatabase::PGresultAutoPtr
00052 {
00053 private:
00054   PGresult* result_;
00055 public:
00056   PGresultAutoPtr(PGresult *ptr) : result_(ptr){}
00057   ~PGresultAutoPtr(){PQclear(result_);}
00058   void reset(PGresult *ptr){PQclear(result_); result_=ptr;}
00059   PGresult* operator * (){return result_;}
00060 };
00061 
00062 
00063 void PostgresqlDatabase::pgMDBconstruct(std::string host, std::string port, std::string user,
00064                                                  std::string password, std::string dbname )
00065 {
00066   std::string conn_info = "host=" + host + " port=" + port + 
00067     " user=" + user + " password=" + password + " dbname=" + dbname;
00068   connection_= PQconnectdb(conn_info.c_str());
00069   if (PQstatus(connection_)!=CONNECTION_OK) 
00070   {
00071     ROS_ERROR("Database connection failed with error message: %s", PQerrorMessage(connection_));
00072   }
00073 }
00074 
00075 PostgresqlDatabase::PostgresqlDatabase(const PostgresqlDatabaseConfig &config)
00076   : in_transaction_(false)
00077 {
00078   pgMDBconstruct(config.getHost(), config.getPort(), config.getUser(), 
00079                  config.getPassword(), config.getDBname());
00080 }
00081 
00082 PostgresqlDatabase::PostgresqlDatabase(std::string host, std::string port, std::string user,
00083                                                  std::string password, std::string dbname )
00084   : in_transaction_(false)
00085 {
00086   pgMDBconstruct(host, port, user, password, dbname);
00087 }
00088 
00089 PostgresqlDatabase::~PostgresqlDatabase()
00090 {
00091   PQfinish(connection_);
00092 }
00093 
00094 bool PostgresqlDatabase::isConnected() const
00095 {
00096   if (PQstatus(connection_)==CONNECTION_OK) return true;
00097   else return false;
00098 }
00099 
00101 bool PostgresqlDatabase::rollback()
00102 {
00103   PGresultAutoPtr result((PQexec(connection_,"ROLLBACK;")));
00104   if (PQresultStatus(*result) != PGRES_COMMAND_OK)
00105   {
00106     ROS_ERROR("Rollback failed");
00107     return false;
00108   }
00109   in_transaction_ = false;
00110   return true;
00111 }
00112 
00114 bool PostgresqlDatabase::begin()
00115 {
00116   if( in_transaction_ ) return true;
00117   
00118   PGresultAutoPtr result(PQexec(connection_, "BEGIN;"));
00119   if (PQresultStatus(*result) != PGRES_COMMAND_OK)
00120   {
00121     ROS_ERROR("Database begin query failed. Error: %s", PQresultErrorMessage(*result));
00122     return false;
00123   }
00124   in_transaction_ = true;
00125   return true;
00126 }
00127 
00129 bool PostgresqlDatabase::commit()
00130 {
00131   PGresultAutoPtr result(PQexec(connection_, "COMMIT;"));
00132   if (PQresultStatus(*result) != PGRES_COMMAND_OK)
00133   {
00134     ROS_ERROR("Database commit query failed. Error: %s", PQresultErrorMessage(*result));
00135     return false;
00136   }
00137   in_transaction_ = false;
00138   return true;
00139 }
00140 
00141 bool PostgresqlDatabase::getVariable(std::string name, std::string &value) const
00142 {
00143   std::string query("SELECT variable_value FROM variable WHERE variable_name=" + name);
00144   PGresultAutoPtr result(PQexec(connection_, query.c_str()));  
00145   if (PQresultStatus(*result) != PGRES_TUPLES_OK)
00146   {
00147     ROS_ERROR("Database get variable query failed. Error: %s", PQresultErrorMessage(*result));
00148     return false;
00149   }
00150   if (PQntuples(*result)==0)
00151   {
00152     ROS_ERROR("Database get variable query failed. Variable %s not in database", name.c_str());
00153     return false;
00154   }
00155   value = PQgetvalue(*result, 0, 0);
00156   return true;
00157 }
00158 
00162 bool PostgresqlDatabase::getSequence(std::string name, std::string &value)
00163 {
00164   std::string query("SELECT * FROM currval('" + name + "');");
00165   PGresultAutoPtr result( PQexec(connection_, query.c_str()) );
00166   if (PQresultStatus(*result) != PGRES_TUPLES_OK)
00167   {
00168     ROS_ERROR("Get sequence: query failed. Error: %s", PQresultErrorMessage(*result));
00169     return false;
00170   }
00171   if (!PQntuples(*result))
00172   {
00173     ROS_ERROR("Get sequence: sequence %s not found", name.c_str());
00174     return false;
00175   }
00176   const char *id_char = PQgetvalue(*result, 0, 0);
00177   value.assign(id_char);
00178   return true;
00179 }
00180 
00190 bool PostgresqlDatabase::getListRawResult(const DBClass *example, 
00191                                                    std::vector<const DBFieldBase*> &fields, 
00192                                                    std::vector<int> &column_ids,
00193                                                    std::string where_clause,
00194                                                    boost::shared_ptr<PGresultAutoPtr> &result, int &num_tuples) const
00195 {
00196   
00197   
00198   if(example->getPrimaryKeyField()->getType() == DBFieldBase::BINARY)
00199   {
00200     ROS_ERROR("Database get list: can not use binary primary key (%s)", 
00201               example->getPrimaryKeyField()->getName().c_str());
00202     return false;
00203   }
00204 
00205   std::string select_query;
00206   select_query += "SELECT " + example->getPrimaryKeyField()->getName() + " ";  
00207   fields.push_back(example->getPrimaryKeyField());
00208 
00209   
00210   std::vector<std::string> join_tables;
00211   std::string join_clauses;
00212   for (size_t i=0; i<example->getNumFields(); i++)
00213   {
00214     if (!example->getField(i)->getReadFromDatabase()) continue;
00215 
00216     if (example->getField(i)->getType()==DBFieldBase::BINARY)
00217     {
00218       ROS_WARN("Database get list: binary field (%s) can not be loaded by default", 
00219                example->getField(i)->getName().c_str());
00220       continue;
00221     }
00222 
00223     select_query += ", " + example->getField(i)->getName();
00224     fields.push_back(example->getField(i));
00225     if ( example->getField(i)->getTableName() != example->getPrimaryKeyField()->getTableName() )
00226     {
00227       
00228       bool already_join = false;
00229       for (size_t j=0; j<join_tables.size() && !already_join; j++)
00230       {
00231         if (join_tables[j] == example->getField(i)->getTableName()) already_join = true;
00232       }
00233       
00234       if (!already_join)
00235       {
00236         const DBFieldBase *foreign_key = NULL;
00237         if (!example->getForeignKey(example->getField(i)->getTableName(), foreign_key))
00238         {
00239           ROS_ERROR("Database get list: could not find foreign key for table %s", 
00240                     example->getField(i)->getTableName().c_str());
00241           return false;
00242         }
00243         join_clauses += " JOIN " + example->getField(i)->getTableName() + " USING (" 
00244           + foreign_key->getName() + ") ";
00245         join_tables.push_back( example->getField(i)->getTableName() );
00246       }
00247     }
00248   }
00249 
00250   select_query += " FROM " + example->getPrimaryKeyField()->getTableName() + " ";
00251 
00252   if (!join_clauses.empty())
00253   {
00254     select_query += join_clauses;
00255   }
00256 
00257   if (!where_clause.empty())
00258   {
00259     select_query += " WHERE " + where_clause;
00260   }
00261 
00262   select_query += ";";
00263 
00264   
00265 
00266   PGresult* raw_result = PQexec(connection_, select_query.c_str());
00267   result.reset( new PGresultAutoPtr(raw_result) );
00268   if (PQresultStatus(raw_result) != PGRES_TUPLES_OK)
00269   {
00270     ROS_ERROR("Database get list: query failed. Error: %s", PQresultErrorMessage(raw_result));
00271     return false;
00272   }
00273   
00274   num_tuples = PQntuples(raw_result);
00275   if (!num_tuples) 
00276   {
00277     return true;
00278   }
00279   
00280   
00281   for (size_t t=0; t<fields.size(); t++)
00282   {
00283     int id =  PQfnumber(raw_result, fields[t]->getName().c_str());
00284     if (id < 0)
00285     {
00286       ROS_ERROR("Database get list: column %s missing in result", fields[t]->getName().c_str());
00287       return false;
00288     }
00289     column_ids.push_back(id);
00290   }   
00291   return true;
00292 }
00293 
00298 bool PostgresqlDatabase::populateListEntry(DBClass *entry, boost::shared_ptr<PGresultAutoPtr> result, 
00299                                                     int row_num,
00300                                                     const std::vector<const DBFieldBase*> &fields,
00301                                                     const std::vector<int> &column_ids) const
00302 {
00303   for (size_t t=0; t<fields.size(); t++)
00304   {
00305     const char* char_value =  PQgetvalue(**result, row_num, column_ids[t]);
00306     DBFieldBase *entry_field = entry->getField(fields[t]->getName());
00307     if (!entry_field)
00308     {
00309       ROS_ERROR("Database get list: new entry missing field %s", fields[t]->getName().c_str());
00310       return false;
00311     }
00312     if ( !entry_field->fromString(char_value) )
00313     {
00314       ROS_ERROR("Database get list: failed to parse response \"%s\" for field \"%s\"",   
00315                 char_value, fields[t]->getName().c_str()); 
00316       return false;
00317     }
00318   }
00319   return true;
00320 }
00321 
00328 bool PostgresqlDatabase::countList(const DBClass *example, int &count, std::string where_clause) const
00329 {
00330   const DBFieldBase* pk_field = example->getPrimaryKeyField();
00331   
00332   std::string query( "SELECT COUNT(" + pk_field->getName() + ") FROM " + pk_field->getTableName() );
00333   if (!where_clause.empty())
00334   {
00335     query += " WHERE " + where_clause;
00336   }
00337   query += ";";
00338 
00339   ROS_INFO("Query (count): %s", query.c_str());
00340   PGresultAutoPtr result( PQexec(connection_, query.c_str()) );
00341                          
00342   if (PQresultStatus(*result) != PGRES_TUPLES_OK)
00343   {
00344     ROS_ERROR("Database count list query failed. Error: %s", PQresultErrorMessage(*result));
00345     return false;
00346   }
00347   const char *reply =  PQgetvalue(*result, 0, 0);
00348   if (!DBStreamable<int>::streamableFromString(count, reply)) 
00349   {
00350     ROS_ERROR("Database count list failed. Could not understand reply: %s", reply);
00351     return false;
00352   }
00353   return true;  
00354 }
00355 
00362 bool PostgresqlDatabase::saveToDatabase(const DBFieldBase* field)
00363 {
00364   if (!field->getWritePermission())
00365   {
00366     ROS_ERROR("Database save field: field %s does not have write permission", field->getName().c_str());
00367     return false;
00368   }
00369 
00370   const DBFieldBase* key_field;
00371   if (field->getTableName() == field->getOwner()->getPrimaryKeyField()->getTableName()) 
00372   {
00373     key_field = field->getOwner()->getPrimaryKeyField();
00374   }
00375   else 
00376   {
00377     if (!field->getOwner()->getForeignKey(field->getTableName(), key_field))
00378     {
00379       ROS_ERROR("Database save field: could not find foreign key for table %s", 
00380                 field->getTableName().c_str());
00381       return false;
00382     }
00383     
00384     
00385   }
00386  
00387   
00388 
00389   std::string query("UPDATE " + field->getTableName() + 
00390                     " SET " + field->getName() + "=$2"
00391                     " WHERE " + key_field->getName() + "=$1;");
00392 
00393   std::vector<const char*> param_values(2);
00394   std::vector<int> param_lengths(2);
00395   std::vector<int> param_formats(2);
00396   
00397   std::string id_str;
00398   if (!key_field->toString(id_str))
00399   {
00400     ROS_ERROR("Database save field: failed to convert key id value to string");
00401     return false;
00402   }
00403   param_formats[0] = 0;
00404   param_values[0] = id_str.c_str();
00405 
00406   
00407   std::string value_str;
00408   if (field->getType() == DBFieldBase::TEXT)
00409   {
00410     if (!field->toString(value_str)) 
00411     {
00412       ROS_ERROR("Database save field: failed to convert field value to string");
00413       return false;
00414     }
00415     param_formats[1] = 0;
00416     param_values[1] = value_str.c_str();
00417   }
00418   else if (field->getType() == DBFieldBase::BINARY)
00419   {
00420     size_t length;
00421     if (!field->toBinary(param_values[1], length))
00422     {
00423       ROS_ERROR("Database save field: failed to convert field value to binary");
00424       return false;
00425     }
00426     param_lengths[1] = length;
00427     param_formats[1] = 1;
00428   }
00429   else
00430   {
00431     ROS_ERROR("Database save field: unkown field type");
00432     return false;
00433   }
00434 
00435   
00436 
00437   PGresultAutoPtr result( PQexecParams(connection_, query.c_str(), 2, 
00438                                        NULL, ¶m_values[0], ¶m_lengths[0], ¶m_formats[0], 0) );
00439   if (PQresultStatus(*result) != PGRES_COMMAND_OK)
00440   {
00441     ROS_ERROR("Database save field: query failed. Error: %s", PQresultErrorMessage(*result));
00442     return false;
00443   }
00444   return true;
00445 }
00446 
00452 bool PostgresqlDatabase::loadFromDatabase(DBFieldBase* field) const
00453 {
00454   const DBFieldBase* key_field = NULL;
00455   if (field->getTableName() == field->getOwner()->getPrimaryKeyField()->getTableName())
00456   {
00457     key_field = field->getOwner()->getPrimaryKeyField();
00458   }
00459   else 
00460   {
00461     if (!field->getOwner()->getForeignKey(field->getTableName(), key_field))
00462     {
00463       ROS_ERROR("Database load field: could not find foreign key for table %s", 
00464                 field->getTableName().c_str());
00465       return false;
00466     }
00467   }
00468 
00469   std::string id_str;
00470   if (!key_field->toString(id_str))
00471   {
00472     ROS_ERROR("Database load field: failed to convert key id value to string");
00473     return false;
00474   }
00475 
00476   std::string query("SELECT " + field->getName() + " FROM " + field->getTableName() + 
00477                     " WHERE " + key_field->getName() + " ='" + id_str + "';");
00478 
00479   
00480 
00481   int data_type;
00482   if (field->getType() == DBFieldBase::TEXT) data_type = 0;
00483   else if (field->getType() == DBFieldBase::BINARY) data_type = 1;
00484   else
00485   {
00486     ROS_ERROR("Database load field: unkown field type");
00487     return false;
00488   }
00489 
00490   PGresultAutoPtr result( PQexecParams(connection_, query.c_str(), 0, NULL, NULL, NULL, NULL, data_type) );
00491   if (PQresultStatus(*result) != PGRES_TUPLES_OK)
00492   {
00493     ROS_ERROR("Database load field: query failed. Error: %s", PQresultErrorMessage(*result));
00494     return false;
00495   }
00496 
00497   if (PQntuples(*result)==0)
00498   {
00499     ROS_ERROR("Database load field: no entry found for key value %s on column %s", 
00500               id_str.c_str(), key_field->getName().c_str());
00501     return false;
00502   }
00503 
00504   const char* result_char =  PQgetvalue(*result, 0, 0);
00505   if (field->getType() == DBFieldBase::TEXT)
00506   {
00507     if ( !field->fromString(result_char) )
00508     {
00509       ROS_ERROR("Database load field: failed to parse text result \"%s\" for field \"%s\"", 
00510                 result_char, field->getName().c_str()); 
00511       return false;
00512     }
00513   } 
00514   else if (field->getType() == DBFieldBase::BINARY)
00515   {
00516     size_t length = PQgetlength(*result, 0, 0);
00517     if (!field->fromBinary(result_char, length))
00518     {
00519       ROS_ERROR("Database load field: failed to parse binary result length %d for field \"%s\"",
00520                 (int) length, field->getName().c_str()); 
00521       return false;
00522     }
00523   }
00524   else
00525   {
00526     ROS_ERROR("Database load field: failed to parse unkown field type");
00527     return false;
00528   }
00529 
00530   return true;
00531 }
00532 
00541 bool PostgresqlDatabase::insertIntoTable(std::string table_name,
00542                                                   const std::vector<const DBFieldBase*> &fields)
00543 {
00544   if (fields.empty())
00545   {
00546     ROS_ERROR("Insert into table: no columns to insert");
00547     return false;
00548   }
00549 
00550   std::string query("INSERT INTO " + table_name + "(");
00551 
00552   
00553   if (table_name == fields[0]->getTableName())
00554   {
00555     
00556     query += fields[0]->getName();
00557   }
00558   else
00559   {
00560     
00561     const DBFieldBase *foreign_key = NULL;
00562     if (!fields[0]->getOwner()->getForeignKey(table_name, foreign_key))
00563     {
00564       ROS_ERROR("Database insert into table: could not find foreign key for table %s", table_name.c_str());
00565       return false;
00566     }
00567     query += foreign_key->getName();
00568   }
00569 
00570   for(size_t i=1; i<fields.size(); i++)
00571   {
00572     query += "," + fields[i]->getName();
00573   }
00574   query += ")";
00575 
00576   query += "VALUES(";
00577   for (size_t i=0; i<fields.size(); i++)
00578   {
00579     if ( i!=0 && table_name!=fields[i]->getTableName())
00580     {
00581       ROS_ERROR("Database insert into table: field table does not match table name");
00582       return false;
00583     }
00584     if (i!=0) query += ",";
00585     std::ostringstream ss;
00586     ss << i+1;
00587     query += "$" + ss.str();
00588   }
00589   query += ");";
00590   
00591   
00592 
00593   
00594   std::vector<std::string> param_strings(fields.size());
00595   std::vector<const char*> param_values(fields.size());
00596   std::vector<int> param_lengths(fields.size());
00597   std::vector<int> param_formats(fields.size());
00598   for (size_t i=0; i<fields.size(); i++)
00599   {
00600     if (fields[i]->getType() == DBFieldBase::TEXT)
00601     {
00602       if (!fields[i]->toString(param_strings[i]))
00603       {
00604         ROS_ERROR("Database insert into table: could not parse field %s", fields[i]->getName().c_str());
00605         return false;
00606       }
00607       param_values[i] = param_strings[i].c_str();
00608       param_formats[i] = 0;
00609     }
00610     else if (fields[i]->getType() == DBFieldBase::BINARY)
00611     {
00612       size_t length;
00613       if (!fields[i]->toBinary(param_values[i], length))
00614       {
00615         ROS_ERROR("Database insert into table: could not binarize field %s", fields[i]->getName().c_str());
00616         return false;
00617       }
00618       param_lengths[i] = length;
00619       param_formats[i] = 1;
00620     }
00621     else
00622     {
00623       ROS_ERROR("Database insert into table: unknown field type");
00624       return false;
00625     }
00626   }
00627 
00628   
00629   PGresultAutoPtr result( PQexecParams(connection_, query.c_str(), fields.size(), NULL, 
00630                                        &(param_values[0]), &(param_lengths[0]), &(param_formats[0]), 0) );
00631   if (PQresultStatus(*result) != PGRES_COMMAND_OK)
00632   {
00633     ROS_ERROR("Database insert into table: query failed.\nError: %s.\nQuery: %s",
00634               PQresultErrorMessage(*result), query.c_str());
00635     return false;
00636   }
00637 
00638   return true;
00639 }
00640 
00647 bool PostgresqlDatabase::insertIntoDatabase(DBClass* instance)
00648 {
00649   
00650   DBFieldBase* pk_field = instance->getPrimaryKeyField();
00651   if (pk_field->getType() != DBFieldBase::TEXT)
00652   {
00653     ROS_ERROR("Database insert: cannot insert binary primary key %s", pk_field->getName().c_str());
00654     return false;
00655   }
00656 
00657   
00658   std::vector<std::string> table_names;
00659   std::vector< std::vector<const DBFieldBase*> > table_fields;
00660 
00661   
00662   table_names.push_back(pk_field->getTableName());
00663   table_fields.push_back( std::vector<const DBFieldBase*>() );
00664   
00665   bool insert_pk;
00666   if (pk_field->getWriteToDatabase())
00667   {
00668     
00669     table_fields.back().push_back(pk_field);
00670     insert_pk = true;
00671   }
00672   else
00673   {
00674     
00675     
00676     if (pk_field->getSequenceName().empty())
00677     {
00678       ROS_ERROR("Database insert: attempt to insert instance without primary key and no sequence for it");
00679       return false;
00680     }
00681     insert_pk = false;
00682   }
00683   
00684   
00685   
00686   
00687   for (size_t i=0; i<instance->getNumFields(); i++)
00688   {
00689     
00690     bool found = false;
00691     size_t t;
00692     for (t=0; t<table_names.size(); t++)
00693     {
00694       if ( table_names[t] == instance->getField(i)->getTableName() )
00695       {
00696         found = true;
00697         break;
00698       }
00699     }
00700     if (!found)
00701     {
00702       
00703       const DBFieldBase* foreign_key = NULL;
00704       if (!instance->getForeignKey(instance->getField(i)->getTableName(), foreign_key))
00705       {
00706         ROS_ERROR("Database insert into table: could not find foreign key for table %s", 
00707           instance->getField(i)->getTableName().c_str());
00708         return false;
00709       }
00710       if (foreign_key != pk_field) 
00711       {
00712         continue;
00713       }
00714       
00715       table_names.push_back( instance->getField(i)->getTableName() );
00716       table_fields.push_back( std::vector<const DBFieldBase*>() );
00717       
00718       
00719       table_fields.back().push_back(pk_field);
00720       t = table_names.size() - 1;
00721     }
00722     if ( !instance->getField(i)->getWriteToDatabase() ) continue;
00723     if ( instance->getField(i)->getType() != DBFieldBase::TEXT )
00724     {
00725       ROS_WARN("Database insert: cannot insert binary field %s in database", 
00726         instance->getField(i)->getName().c_str());
00727       continue;
00728     }
00729     
00730     table_fields[t].push_back(instance->getField(i));
00731   }
00732   
00733   
00734   if (!begin()) return false;
00735 
00736   
00737   if (!insertIntoTable(table_names[0], table_fields[0])) 
00738   {
00739     rollback();
00740     return false;
00741   }
00742 
00743   
00744   if (!insert_pk)
00745   {
00746     std::string sequence_value;
00747     if (!getSequence(pk_field->getSequenceName(), sequence_value) || !pk_field->fromString(sequence_value))
00748     {
00749       ROS_ERROR("Database insert: failed to retrieve primary key after insertion");
00750       rollback();
00751       return false;
00752     }
00753   }
00754 
00755   
00756   for (size_t i=1; i<table_names.size(); i++)
00757   {
00758     if (!insertIntoTable(table_names[i], table_fields[i]))
00759     {
00760       rollback();
00761       return false;
00762     }
00763   }
00764 
00765   
00766   if (!commit()) return false;
00767 
00768   return true;
00769 }
00770 
00772 bool PostgresqlDatabase::deleteFromTable(std::string table_name, const DBFieldBase *key_field)
00773 {
00774   std::string id_str;
00775   if (!key_field->toString(id_str))
00776   {
00777     ROS_ERROR("Database delete from table: failed to convert key id value to string");
00778     return false;
00779   }
00780 
00781   std::string query("DELETE FROM " + table_name + " WHERE " + key_field->getName() + "=" + id_str);
00782   PGresultAutoPtr result( PQexec(connection_, query.c_str()) );
00783   if (PQresultStatus(*result) != PGRES_COMMAND_OK)
00784   {
00785     ROS_ERROR("Database delete from table: query failed. Error: %s", PQresultErrorMessage(*result));
00786     return false;
00787   }
00788   return true;
00789 }
00790 
00794 bool PostgresqlDatabase::deleteFromDatabase(DBClass* instance)
00795 {
00796   std::vector<std::string> table_names;
00797   std::vector<const DBFieldBase*> table_fields;
00798   DBFieldBase* pk_field = instance->getPrimaryKeyField();
00799   
00800   table_names.push_back( pk_field->getTableName() );
00801   table_fields.push_back( pk_field );
00802   
00803   for (size_t i=0; i<instance->getNumFields(); i++)
00804   {
00805     
00806     size_t t;
00807     for (t=0; t<table_names.size(); t++)
00808     {
00809       if ( table_names[t] == instance->getField(i)->getTableName() ) break;
00810     }
00811     if (t<table_names.size()) continue;
00812 
00813     
00814     const DBFieldBase* foreign_key = NULL;
00815     if (!instance->getForeignKey(instance->getField(i)->getTableName(), foreign_key))
00816     {
00817       ROS_ERROR("Database insert into table: could not find foreign key for table %s", 
00818                 instance->getField(i)->getTableName().c_str());
00819       return false;
00820     }
00821     if (foreign_key != pk_field) continue;
00822 
00823     
00824     table_names.push_back( instance->getField(i)->getTableName() );
00825     table_fields.push_back( pk_field );
00826   }
00827 
00828   
00829   if (!begin()) return false;
00830   
00831   
00832   for (int i=(int)table_names.size()-1; i>=0; i--)
00833   {
00834     if (!deleteFromTable(table_names[i], table_fields[i]))
00835     {
00836       rollback();
00837       return false;
00838     }
00839   }
00840 
00841   
00842   if (!commit()) return false;
00843 
00844   return true;
00845 
00846 }
00847 
00848 }