// AmiSqlTable.cxx #include "dial_ws_ami/AmiSqlTable.h" #include "dataset_sql/SqlResult.h" #include "dataset_xml/XmlParser.h" #include "dataset_util/XmlElement.h" #include "../gsoap/dial_ws_amiAMIWebServiceSoapBindingProxy.h" #include #include #include #include using std::cout; using std::endl; using std::string; using std::istringstream; using std::stringstream; using std::vector; using std::map; using dset::SelectQuery; using dset::InsertQuery; using dset::DeleteQuery; using dset::SqlTable; using dset::SqlResult; using dial::AmiSqlTable; //********************************************************************** //Local Definitions. //********************************************************************** namespace { // Creator. SqlTable* create(string tech, string name) { AmiSqlTable *pm_table = new AmiSqlTable(name); return pm_table; } //********************************************************************** // Register creator. int STAT_AmiSqlTable = SqlTable::register_creator("AMI", create); //********************************************************************** } // end unnamed namespace //********************************************************************** // Member functions. //********************************************************************** // Constructor. AmiSqlTable::AmiSqlTable(string params) : m_error(0), m_valid(false) { string::size_type ipos, jpos; ipos = params.find(":"); m_project = params.substr(0, ipos); jpos = params.find(":", ipos+1); m_table = params.substr(ipos+1, jpos-(ipos+1)); ipos = params.find(":", jpos+1); m_pstep = params.substr(jpos+1, ipos-(jpos+1)); jpos = params.find(":", ipos+1); m_uname = params.substr(ipos+1, jpos-(ipos+1)); m_passwd = params.substr(jpos+1); // Build the AMI Map object amiType__Map input; amiType__mapItem ele; vector plist; vector pitem; ele.key = new string("command"); ele.value = new string("ListEntityProperties"); plist.push_back(ele); ele.key = new string("AMIUser"); ele.value = new string(m_uname); plist.push_back(ele); ele.key = new string("AMIPass"); ele.value = new string(m_passwd); plist.push_back(ele); ele.key = new string("project"); ele.value = new string(m_project); plist.push_back(ele); ele.key = new string("processingStep"); ele.value = new string(m_pstep); plist.push_back(ele); ele.key = new string("entity"); ele.value = new string(m_table); plist.push_back(ele); for ( vector::iterator it = plist.begin(); it != plist.end(); ++it) pitem.push_back(&(*it)); input.item = pitem; AMIWebServiceSoapBinding amiObj; //2.7.0f struct ami__execAMICommand_USCOREmapResponse result; //2.7.0f int stat = amiObj.ami__execAMICommand_USCOREmap(&input, result); string sresult; int stat = amiObj.ami__execAMICommand_USCOREmap(&input, sresult); // Deallocate for ( vector::iterator ivec = pitem.begin(); ivec != pitem.end(); ++ivec) { delete (*ivec)->key; delete (*ivec)->value; } if(stat == SOAP_OK) m_valid = true; } //********************************************************************** // Destructor. AmiSqlTable::~AmiSqlTable() { } //********************************************************************** // Validity. bool AmiSqlTable::is_valid() const { return m_valid; } //********************************************************************** // Error code. int AmiSqlTable::error() const { return m_error; } //********************************************************************** // Return a string describing the error. string AmiSqlTable::error_string(int ecode) const { if( ecode == 0 ) return "No error"; if( ecode == 1 ) return "Invalid query"; if( ecode == 2 ) return "No such element in repository"; if( ecode == 3 ) return "Empty query"; if( ecode == 4 ) return "Updates not allowed"; return "Unknown error"; } //********************************************************************** // Displays the database schema. SqlResult AmiSqlTable::get_schema() const { // Exit if this table is invalid. if ( !is_valid() ) return SqlResult(); // Initialize error code. m_error = 0; // Build the AMI Map object amiType__Map input; amiType__mapItem ele; vector plist; vector pitem; ele.key = new string("command"); ele.value = new string("ListEntityProperties"); plist.push_back(ele); ele.key = new string("AMIUser"); ele.value = new string(m_uname); plist.push_back(ele); ele.key = new string("AMIPass"); ele.value = new string(m_passwd); plist.push_back(ele); ele.key = new string("project"); ele.value = new string(m_project); plist.push_back(ele); ele.key = new string("processingStep"); ele.value = new string(m_pstep); plist.push_back(ele); ele.key = new string("entity"); ele.value = new string(m_table); plist.push_back(ele); for ( vector::iterator it = plist.begin(); it != plist.end(); ++it) pitem.push_back(&(*it)); input.item = pitem; AMIWebServiceSoapBinding amiObj; //2.7.0f struct ami__execAMICommand_USCOREmapResponse result; //2.7.0f int stat = amiObj.ami__execAMICommand_USCOREmap(&input, result); string sresult; int stat = amiObj.ami__execAMICommand_USCOREmap(&input, sresult); // Deallocate for ( vector::iterator ivec = pitem.begin(); ivec != pitem.end(); ++ivec) { delete (*ivec)->key; delete (*ivec)->value; } if(stat != SOAP_OK) { m_error = 1; return SqlResult(); } //2.7.0f string sresult(result._execAMICommand_USCOREmapReturn); string::size_type ipos = 0; while(sresult[ipos] != '>') ++ipos; string res = sresult.substr(ipos+2, sresult.size()); assert( res.size() != 0 ); XmlParser par; const XmlElement *pres = par.parse(res); assert( pres->is_valid() ); const XmlElement *presult = pres->single_child("Result"); const XmlElement *prowset = presult->single_child("rowset"); XmlElement::ElementList rows = prowset->children("row"); assert( rows.size() == 9 ); SqlResult::NameList cols; SqlResult::Row newrow; for ( XmlElement::ElementList::const_iterator iele = rows.begin(); iele != rows.end(); ++iele ) { XmlElement::ElementList fields = (*iele)->children("field"); assert( fields.size() != 0 ); const XmlElement &field = *fields[0]; const XmlElement &type = *fields[1]; string col = field.pcdata(); string coltype = type.pcdata(); cols.push_back(col); newrow[col] = coltype; } SqlResult sqlres(cols); sqlres.insert_row(newrow); return sqlres; } //********************************************************************** // Fetch the description of the column holding the modification time. std::string AmiSqlTable::modify_time_column() const { return ""; } //********************************************************************** // Fetch the description of the column holding the creation time. std::string AmiSqlTable::create_time_column() const { return ""; } //********************************************************************** // Fetch the number of rows. // If query is empty then, return the number of rows in entire m_table // else, return the number of rows in the result of the query int AmiSqlTable::get_row_count(SelectQuery query) const { // Exit if this table is invalid. if ( !is_valid() ) return 0; // Initialize error code. m_error = 0; // Extract the constraint if present string sql; string con = query.get_constraint(); // If constraint is not empty, append "where" and // then the constraint. if(con.size() != 0) sql = "select count(*) from " + m_table + " where " + con; else sql = "select count(*) from " + m_table; // Build the AMI Map object struct ami__execAMICommand_USCOREmapResponse result; amiType__Map input; amiType__mapItem ele; vector plist; vector pitem; ele.key = new string("command"); ele.value = new string("SearchQuery"); plist.push_back(ele); ele.key = new string("AMIUser"); ele.value = new string(m_uname); plist.push_back(ele); ele.key = new string("AMIPass"); ele.value = new string(m_passwd); plist.push_back(ele); ele.key = new string("project"); ele.value = new string(m_project); plist.push_back(ele); ele.key = new string("processingStep"); ele.value = new string(m_pstep); plist.push_back(ele); ele.key = new string("sql"); ele.value = new string(sql); plist.push_back(ele); for ( vector::iterator it = plist.begin(); it != plist.end(); ++it) pitem.push_back(&(*it)); input.item = pitem; AMIWebServiceSoapBinding amiObj; //2.7.0f int stat = amiObj.ami__execAMICommand_USCOREmap(&input, result); string sresult; int stat = amiObj.ami__execAMICommand_USCOREmap(&input, sresult); // Deallocate for ( vector::iterator ivec = pitem.begin(); ivec != pitem.end(); ++ivec) { delete (*ivec)->key; delete (*ivec)->value; } if ( stat != SOAP_OK ) { m_error = 1; return 0; } //2.7.0f string sresult(result._execAMICommand_USCOREmapReturn); // Iterate past the version header string::size_type ipos = 0; while( sresult[ipos] != '>' ) ++ipos; string res = sresult.substr(ipos+2, sresult.size()); XmlParser par; const XmlElement *pres = par.parse(res); assert( pres->is_valid() ); const XmlElement *presult = pres->single_child("result"); const XmlElement *prowset = presult->single_child("rowset"); const XmlElement *row = prowset->single_child("row"); const XmlElement *field = row->single_child("field"); string value = field->pcdata(); return atoi(value.c_str()); } //********************************************************************** // Fetch the number of columns // If empty query, return the number of columns in schema // Otherwise, return the number of columns in the result int AmiSqlTable::get_col_count(SelectQuery query) const { // Exit if this table is invalid. if ( !is_valid() ) return 0; // Initialize error code. m_error = 0; string con = query.get_constraint(); if(con.size() == 0) { SqlResult res = get_schema(); SqlResult::Row row = res.fetch_row(0); return row.size(); } SqlResult res = execute_select_query(query); if(!res.is_valid()) { m_error = 1; return 0; } return res.num_cols(); } //********************************************************************** // Execute a select query SqlResult AmiSqlTable::execute_select_query(const SelectQuery query) const { // Exit if this table is invalid. if ( !is_valid() ) return SqlResult(); // Initialize error code. m_error = 0; //Insert the list of desired columns into a vector string::size_type ipos, jpos; string scol; string params = query.get_columns(); if (params.size() != 0) scol = params; else scol = "*"; // Extract the constraint if present string sql; string con = query.get_constraint(); // If constraint is not empty, check for keyword "limit" // and appropriately append "where" and then the constraint. if(con.size() != 0) { if(((ipos = con.find("limit")) != string::npos) && ipos == 0) sql = "select " + scol + " from " + m_table + " " + con; else sql = "select " + scol + " from " + m_table + " where " + con; } else sql = "select " + scol + " from " + m_table; // Build the AMI Map object amiType__Map input; amiType__mapItem ele; vector plist; vector pitem; ele.key = new string("command"); ele.value = new string("SearchQuery"); plist.push_back(ele); ele.key = new string("AMIUser"); ele.value = new string(m_uname); plist.push_back(ele); ele.key = new string("AMIPass"); ele.value = new string(m_passwd); plist.push_back(ele); ele.key = new string("project"); ele.value = new string(m_project); plist.push_back(ele); ele.key = new string("processingStep"); ele.value = new string(m_pstep); plist.push_back(ele); ele.key = new string("sql"); ele.value = new string(sql); plist.push_back(ele); for ( vector::iterator it = plist.begin(); it != plist.end(); ++it) pitem.push_back(&(*it)); input.item = pitem; AMIWebServiceSoapBinding amiObj; //2.7.0f struct ami__execAMICommand_USCOREmapResponse result; //2.7.0f int stat = amiObj.ami__execAMICommand_USCOREmap(&input, result); string sresult; int stat = amiObj.ami__execAMICommand_USCOREmap(&input, sresult); // Deallocate for ( vector::iterator ivec = pitem.begin(); ivec != pitem.end(); ++ivec) { delete (*ivec)->key; delete (*ivec)->value; } if(stat != SOAP_OK) { m_error = 1; return SqlResult(); } //2.7.0f string sresult(result._execAMICommand_USCOREmapReturn); // Iterate past the version header ipos = 0; while( sresult[ipos] != '>' ) ++ipos; string res = sresult.substr(ipos+2, sresult.size()); SqlResult::NameList cols; SqlResult tres = get_schema(); map tmap = tres.fetch_row(0); assert(tmap.size() != 0); for ( map::const_iterator it = tmap.begin(); it != tmap.end(); ++it) cols.push_back(it->first); SqlResult sqlres(cols); // ListElement does not return an error if element is absent // But inserts an extra tag in result // If tag exists, return an empty result jpos = res.find (""); if (jpos != string::npos) { return sqlres; } XmlParser par; const XmlElement *pres = par.parse(res); assert( pres->is_valid() ); const XmlElement *presult = pres->single_child("result"); const XmlElement *prowset = presult->single_child("rowset"); XmlElement::ElementList rows = prowset->children("row"); for ( XmlElement::ElementList::const_iterator iele = rows.begin(); iele != rows.end(); ++iele ) { SqlResult::Row newrow; XmlElement::ElementList fields = (*iele)->children("field"); assert( fields.size() != 0 ); for ( XmlElement::ElementList::const_iterator pele = fields.begin(); pele != fields.end(); ++pele ) { const XmlElement &field = **pele; newrow[field.attribute("name")] = field.pcdata(); } sqlres.insert_row(newrow); } return sqlres; } //********************************************************************** // Execute an insert query // Returns 0 on success int AmiSqlTable::execute_insert_query(InsertQuery query) { // Exit if this table is invalid. if ( !is_valid() ) return 1; // Initialize error code. m_error = 0; SqlResult::Row row = query.get_row(); // Empty query if(row.size() == 0) { m_error = 3; return 1; } // Build the AMI Map object amiType__Map input; amiType__mapItem ele; vector plist; vector pitem; ele.key = new string("command"); ele.value = new string("AddElement"); plist.push_back(ele); ele.key = new string("AMIUser"); ele.value = new string(m_uname); plist.push_back(ele); ele.key = new string("AMIPass"); ele.value = new string(m_passwd); plist.push_back(ele); ele.key = new string("project"); ele.value = new string(m_project); plist.push_back(ele); ele.key = new string("processingStep"); ele.value = new string(m_pstep); plist.push_back(ele); ele.key = new string("entity"); ele.value = new string(m_table); plist.push_back(ele); for ( SqlResult::Row::const_iterator it = row.begin(); it != row.end(); ++it ) { ele.key = new string(it->first); ele.value = new string(it->second); plist.push_back(ele); } for ( vector::iterator it = plist.begin(); it != plist.end(); ++it) pitem.push_back(&(*it)); input.item = pitem; AMIWebServiceSoapBinding amiObj; //2.7.0f struct ami__execAMICommand_USCOREmapResponse result; //2.7.0f int stat = amiObj.ami__execAMICommand_USCOREmap(&input, result); string sresult; int stat = amiObj.ami__execAMICommand_USCOREmap(&input, sresult); // Deallocate for ( vector::iterator ivec = pitem.begin(); ivec != pitem.end(); ++ivec) { delete (*ivec)->key; delete (*ivec)->value; } if(stat != SOAP_OK) { m_error = 1; return 1; } return 0; } //********************************************************************** // Execute an update query // Update queries are not allowed and m_error indicates this error. int AmiSqlTable::execute_update_query(InsertQuery iquery, SelectQuery squery) { m_error = 4; return 1; } //********************************************************************** // Execute a delete query int AmiSqlTable::execute_delete_query(DeleteQuery query) { // Exit if this table is invalid. if ( !is_valid() ) return 1; // Initialize error code. m_error = 0; // Empty query. string con = query.get_constraint(); if(con.size() == 0) { m_error = 3; return 1; } // Build the AMI Map object amiType__Map input; amiType__mapItem ele; vector plist; vector pitem; ele.key = new string("command"); ele.value = new string("RemoveElement"); plist.push_back(ele); ele.key = new string("AMIUser"); ele.value = new string(m_uname); plist.push_back(ele); ele.key = new string("AMIPass"); ele.value = new string(m_passwd); plist.push_back(ele); ele.key = new string("project"); ele.value = new string(m_project); plist.push_back(ele); ele.key = new string("processingStep"); ele.value = new string(m_pstep); plist.push_back(ele); ele.key = new string("entity"); ele.value = new string(m_table); plist.push_back(ele); // If there is an and constraint, split it into 2 constraints string con1; string *att, *op, *val; string::size_type jpos; while(1) { jpos = con.find("and"); if(jpos == string::npos) break; con1 = con.substr(0, jpos-1); con = con.substr(jpos+4); att = new string(); op = new string(); val = new string(); istringstream strm1(con1); strm1 >> *att; strm1 >> *op; strm1 >> *val; // Add the new key-value pair to the AMI map object ele.key = att; ele.value = val; plist.push_back(ele); } att = new string(); op = new string(); val = new string(); istringstream strm2(con); strm2 >> *att; strm2 >> *op; strm2 >> *val; // Add the last key-value pair to the AMI map object ele.key = att; ele.value = val; plist.push_back(ele); for ( vector::iterator it = plist.begin(); it != plist.end(); ++it) pitem.push_back(&(*it)); input.item = pitem; AMIWebServiceSoapBinding amiObj; //2.7.0f struct ami__execAMICommand_USCOREmapResponse result; //2.7.0f int stat = amiObj.ami__execAMICommand_USCOREmap(&input, result); string sresult; int stat = amiObj.ami__execAMICommand_USCOREmap(&input, sresult); // Deallocate for ( vector::iterator ivec = pitem.begin(); ivec != pitem.end(); ++ivec) { delete (*ivec)->key; delete (*ivec)->value; } if(stat != SOAP_OK) { m_error = 1; return 1; } return 0; } //**********************************************************************