virtual void requestBlobsForAttrib(const String& attr, Vector<String>& out ) { String sql = "SELECT " + attr + " FROM " + _srcName; IDBResult res = _db.executeSQL(sql.c_str()); for ( ;!res.isEnd();res.next()) { out.push_back( /*common::CFilePath::join( RHODESAPP().getBlobsDirPath(), */res.getStringByIdx(0)/*)*/ ); } }
unsigned long rhom_make_object(IDBResult& res1, int nSrcID, bool isSchemaSrc) { unsigned long item = 0; if ( res1.isEnd() ) return item; item = rho_connectclient_hash_create(); rho_connectclient_hash_put(item, "source_id", convertToStringA(nSrcID).c_str() ); if (!isSchemaSrc) { for ( ; !res1.isEnd(); res1.next() ) { if ( !res1.isNullByIdx(1) ) rho_connectclient_hash_put(item, res1.getStringByIdx(0).c_str(), res1.getStringByIdx(1).c_str() ); } }else { for (int i = 0; i < res1.getColCount(); i++ ) { if ( !res1.isNullByIdx(i)) rho_connectclient_hash_put(item, res1.getColName(i).c_str(), res1.getStringByIdx(i).c_str() ); } } return item; }
void rho_connectclient_processmodels(RHOM_MODEL* pModels, int nModels) { db::CDBAdapter& oUserDB = db::CDBAdapter::getUserDB(); int nStartModelID = 1; { IDBResult res = oUserDB.executeSQL("SELECT MAX(source_id) AS maxid FROM sources"); if ( !res.isEnd() ) nStartModelID = res.getIntByIdx(0)+2; } //create associations string Hashtable<String, String> hashSrcAssoc; for ( int i = 0; i < nModels; i++ ) { RHOM_MODEL& model = pModels[i]; if ( !model.associations ) continue; Hashtable<String, String>& assocHash = *((Hashtable<String, String>*)model.associations); for ( Hashtable<String,String>::iterator itAssoc = assocHash.begin(); itAssoc != assocHash.end(); ++itAssoc ) { String strAssoc = hashSrcAssoc[itAssoc->second]; if (strAssoc.length() > 0 ) strAssoc += ","; strAssoc += model.name; strAssoc += "," + itAssoc->first; hashSrcAssoc[itAssoc->second] = strAssoc; } } for ( int i = 0; i < nModels; i++ ) { RHOM_MODEL& model = pModels[i]; IDBResult res = oUserDB.executeSQL("SELECT sync_priority,source_id,partition, sync_type, schema_version, associations, blob_attribs FROM sources WHERE name=?", model.name); String strAssoc = hashSrcAssoc[model.name]; if ( !res.isEnd() ) { oUserDB.executeSQL("UPDATE sources SET sync_priority=?, sync_type=?, partition=?, schema=?, schema_version=?, associations=?, blob_attribs=? WHERE name=?", model.sync_priority, getSyncTypeName(model.sync_type), model.partition, (model.type == RMT_PROPERTY_FIXEDSCHEMA ? "schema_model" : ""), "", strAssoc.c_str(), "", model.name ); }else //new model { oUserDB.executeSQL("INSERT INTO sources (source_id,name,sync_priority, sync_type, partition, schema,schema_version, associations, blob_attribs) values (?,?,?,?,?,?,?,?,?) ", nStartModelID, model.name, model.sync_priority, getSyncTypeName(model.sync_type), model.partition, (model.type == RMT_PROPERTY_FIXEDSCHEMA ? "schema_model" : ""), "", strAssoc.c_str(), "" ); nStartModelID++; } } }
boolean CClientRegister::doRegister(CSyncEngine& oSync) { String session = oSync.loadSession(); if ( session.length() == 0 ) { m_nPollInterval = POLL_INTERVAL_INFINITE; LOG(INFO)+"Session is empty, do register later"; return false; } if ( m_strDevicePin.length() == 0 ) { notifyLoggedIn("","",session); m_nPollInterval = POLL_INTERVAL_INFINITE; LOG(INFO)+"Device PUSH pin is empty, do register later"; return false; } m_nPollInterval = POLL_INTERVAL_SECONDS; String client_id = oSync.loadClientID(); if ( client_id.length() == 0 ) { LOG(WARNING)+"Sync client_id is empty, do register later"; return false; } IDBResult res = CDBAdapter::getUserDB().executeSQL("SELECT token,token_sent from client_info"); if ( !res.isEnd() ) { String token = res.getStringByIdx(0); int token_sent = res.getIntByIdx(1) && !RHOCONF().getBool("register_push_at_startup"); if ( m_strDevicePin.compare(token) == 0 && token_sent > 0 ) { //token in db same as new one and it was already send to the server //so we do nothing return true; } } String strBody = getRegisterBody(client_id); NetResponse resp = getNet().pushData( oSync.getProtocol().getClientRegisterUrl(client_id), strBody, &oSync ); if( resp.isOK() ) { CDBAdapter::getUserDB().executeSQL("UPDATE client_info SET token_sent=?, token=?", 1, m_strDevicePin ); LOG(INFO)+"Registered client sucessfully..."; return true; } LOG(WARNING)+"Network error: "+ resp.getRespCode(); return false; }
void rho_connectclient_stop_bulkupdate(const char* szModel) { String src_name = szModel; IDBResult res = db::CDBAdapter::getUserDB().executeSQL("SELECT partition from sources WHERE name=?", src_name); if ( res.isEnd()) { //TODO: report error - unknown source return; } String db_partition = res.getStringByIdx(0); db::CDBAdapter& db = db::CDBAdapter::getDB(db_partition.c_str()); db.endTransaction(); }
unsigned long rho_connectclient_find(const char* szModel,const char* szObject ) { String src_name = szModel; IDBResult res = db::CDBAdapter::getUserDB().executeSQL("SELECT source_id, partition, schema, sync_type from sources WHERE name=?", src_name); if ( res.isEnd()) { //TODO: report error - unknown source return 0; } int nSrcID = res.getIntByIdx(0); String db_partition = res.getStringByIdx(1); bool isSchemaSrc = res.getStringByIdx(2).length() > 0; //String tableName = isSchemaSrc ? src_name : "object_values"; db::CDBAdapter& db = db::CDBAdapter::getDB(db_partition.c_str()); return rhom_load_item_by_object( db, src_name, nSrcID, szObject, isSchemaSrc); }
void CDBAttrManager::loadBlobAttrs(CDBAdapter& db) { loadAttrs(db, m_mapBlobAttrs, "blob_attribs"); for ( HashtablePtr< int, Hashtable<String,int>* >::iterator it = m_mapBlobAttrs.begin(); it != m_mapBlobAttrs.end(); ++it ) { int nSrcID = it->first; IDBResult res = db.executeSQL("SELECT name FROM sources WHERE source_id=?", nSrcID); if ( res.isEnd() ) continue; String strName = res.getStringByIdx(0); if ( !db.isTableExist(strName) ) continue; db.createDeleteTrigger(strName); } }
boolean CClientRegister::doRegister(CSyncEngine& oSync) { String session = oSync.loadSession(); if ( session.length() == 0 ) { m_nPollInterval = POLL_INTERVAL_INFINITE; return false; } m_nPollInterval = POLL_INTERVAL_SECONDS; String client_id = oSync.loadClientID(); if ( client_id.length() == 0 ) return false; IDBResult res = CDBAdapter::getUserDB().executeSQL("SELECT token,token_sent from client_info"); if ( !res.isEnd() ) { String token = res.getStringByIdx(0); int token_sent = res.getIntByIdx(1); if ( m_strDevicePin.compare(token) == 0 && token_sent > 0 ) { //token in db same as new one and it was already send to the server //so we do nothing return true; } } String strBody = getRegisterBody(client_id); NetResponse(resp, getNet().pushData( oSync.getProtocol().getClientRegisterUrl(), strBody, &oSync )); if( resp.isOK() ) { // try { CDBAdapter::getUserDB().executeSQL("UPDATE client_info SET token_sent=?, token=?", 1, m_strDevicePin ); // } catch(Exception ex) { // LOG.ERROR("Error saving token_sent to the DB..."); // } LOG(INFO)+"Registered client sucessfully..."; return true; } else { LOG(INFO)+"Network error POST-ing device pin to the server..."; } return false; }
int CSyncThread::getLastPollInterval() { uint64 nowTime = CLocalTime().toULong(); uint64 latestTimeUpdated = 0; Vector<String> arPartNames = db::CDBAdapter::getDBAllPartitionNames(); for( int i = 0; i < (int)arPartNames.size(); i++ ) { db::CDBAdapter& dbPart = db::CDBAdapter::getDB(arPartNames.elementAt(i).c_str()); IDBResult res = dbPart.executeSQL("SELECT last_updated from sources"); for ( ; !res.isEnd(); res.next() ) { uint64 timeUpdated = res.getUInt64ByIdx(0); if ( latestTimeUpdated < timeUpdated ) latestTimeUpdated = timeUpdated; } } return latestTimeUpdated > 0 ? (int)(nowTime-latestTimeUpdated) : 0; }
unsigned long rho_connectclient_findbysql(const char* szModel, const char* szSql, unsigned long arParams ) { String src_name = szModel; IDBResult res = db::CDBAdapter::getUserDB().executeSQL("SELECT source_id, partition, schema, sync_type from sources WHERE name=?", src_name); if ( res.isEnd()) { //TODO: report error - unknown source return 0; } int nSrcID = res.getIntByIdx(0); String db_partition = res.getStringByIdx(1); bool isSchemaSrc = res.getStringByIdx(2).length() > 0; db::CDBAdapter& db = db::CDBAdapter::getDB(db_partition.c_str()); unsigned long items = rho_connectclient_strhasharray_create(); IDBResult res1 = !arParams ? db.executeSQL(szSql) : db.executeSQLEx( szSql, *((Vector<String>*) arParams) ); if ( res1.isEnd() ) return items; for ( ; !res1.isEnd(); res1.next() ) { unsigned long item = rho_connectclient_hash_create(); for (int i = 0; i < res1.getColCount(); i++ ) { if ( !res1.isNullByIdx(i)) rho_connectclient_hash_put(item, res1.getColName(i).c_str(), res1.getStringByIdx(i).c_str() ); } rho_connectclient_strhasharray_add(items, item ); } return items; }
/*static*/void CDBAttrManager::loadAttrs(CDBAdapter& db, HashtablePtr< int, Hashtable<String,int>* >& mapAttrs, String strDBAttr) { mapAttrs.clear(); String strSql = "SELECT source_id,"; strSql += strDBAttr + " from sources"; IDBResult res = db.executeSQL(strSql.c_str()); for ( ; !res.isEnd(); res.next() ) { int nSrcID = res.getIntByIdx(0); String strAttribs = res.getStringByIdx(1); if ( strAttribs.length() == 0 ) continue; CTokenizer oTokenizer( strAttribs, "," ); Hashtable<String,int>* pmapAttr = new Hashtable<String,int>(); String strAttr = ""; while (oTokenizer.hasMoreTokens()) { String tok = oTokenizer.nextToken(); if (tok.length() == 0) continue; if ( strAttr.length() > 0 ) { int nCounter = 0; convertFromStringA(tok.c_str(),nCounter); pmapAttr->put(strAttr, nCounter); strAttr = ""; }else strAttr = tok; } mapAttrs.put(nSrcID,pmapAttr); } }
Vector<String> CDBRequestHelper::requestBlobs( ) { Vector<String> list; IDBResult res = _db.executeSQL("SELECT source_id, name, schema FROM sources"); for ( ;!res.isEnd();res.next() ) { int srcId = res.getIntByIdx(0); String srcName = res.getStringByIdx(1); boolean isSchemaSource = res.getStringByIdx(2).length() > 0; common::CAutoPtr<BlobsRequest> request; if (isSchemaSource) { request = new FixedSchemaBlobsRequest(_db,srcId,srcName); } else { request = new PropertyBagBlobsRequest(_db,srcId); } request->getBlobs(list); } return list; }
void CDBAttrManager::loadBlobAttrs(CDBAdapter& db) { loadAttrs(db, m_mapBlobAttrs, "blob_attribs"); String strTriggerPrefix = "rhoSchemaTrigger_"; IDBResult res = db.executeSQL( "SELECT name FROM sqlite_master WHERE type='trigger'" ); Hashtable<String,int> mapTriggers; for ( ; !res.isEnd(); res.next() ) { String strName = res.getStringByIdx(0); if ( !String_startsWith(strName, strTriggerPrefix) ) continue; mapTriggers[strName.substr(strTriggerPrefix.length())] = 0; } for ( HashtablePtr< int, Hashtable<String,int>* >::iterator it = m_mapBlobAttrs.begin(); it != m_mapBlobAttrs.end(); ++it ) { int nSrcID = it->first; IDBResult res = db.executeSQL("SELECT name FROM sources WHERE source_id=?", nSrcID); if ( res.isEnd() ) continue; String strName = res.getStringByIdx(0); if ( !db.isTableExist(strName) ) continue; Hashtable<String,int>& hashAttribs = *it->second; for ( Hashtable<String,int>::iterator itAttr = hashAttribs.begin(); itAttr != hashAttribs.end(); ++itAttr ) { String strTriggerName = strName + "_" + itAttr->first; if ( !mapTriggers.containsKey(strTriggerName + "_delete") ) { String strTrigger = String("CREATE TRIGGER ") + strTriggerPrefix + strTriggerName + "_delete BEFORE DELETE ON \"" + strName + "\" FOR EACH ROW \r\n" " BEGIN \r\n" " SELECT rhoOnDeleteSchemaRecord( OLD." + itAttr->first + ");\r\n" " END;\r\n" ";"; db.createTrigger(strTrigger); }else mapTriggers[strTriggerName + "_delete"] = 1; if ( !mapTriggers.containsKey(strTriggerName + "_update") ) { String strTrigger = String("CREATE TRIGGER ") + strTriggerPrefix + strTriggerName + "_update BEFORE UPDATE ON \"" + strName + "\" FOR EACH ROW\r\n" " BEGIN \r\n" " SELECT rhoOnUpdateSchemaRecord( OLD." + itAttr->first + ", NEW." + itAttr->first + ");\r\n" " END;\r\n" ";"; db.createTrigger(strTrigger); }else mapTriggers[strTriggerName + "_update"] = 1; } } //Remove outdated triggers for ( Hashtable<String,int>::iterator itTriggers = mapTriggers.begin(); itTriggers != mapTriggers.end(); ++itTriggers ) { if ( !itTriggers->second ) { db.dropTrigger(strTriggerPrefix+itTriggers->first); } } }
unsigned long rhom_find(const char* szModel, unsigned long hash, int nCount ) { String src_name = szModel; IDBResult res = db::CDBAdapter::getUserDB().executeSQL("SELECT source_id, partition, schema, sync_type from sources WHERE name=?", src_name); if ( res.isEnd()) { //TODO: report error - unknown source return 0; } int nSrcID = res.getIntByIdx(0); String strSrcID = convertToStringA(nSrcID); String db_partition = res.getStringByIdx(1); bool isSchemaSrc = res.getStringByIdx(2).length() > 0; //String tableName = isSchemaSrc ? src_name : "object_values"; db::CDBAdapter& db = db::CDBAdapter::getDB(db_partition.c_str()); Hashtable<String, String>& hashCond = *((Hashtable<String, String>*)hash); String sql = ""; Vector<String> arValues; if (!isSchemaSrc) { if (hashCond.size() == 0) { sql = "SELECT distinct(object) FROM object_values WHERE source_id=?"; arValues.addElement(strSrcID); }else { for ( Hashtable<String,String>::iterator it = hashCond.begin(); it != hashCond.end(); ++it ) { if ( sql.length() > 0 ) sql += "\nINTERSECT\n"; sql += "SELECT object FROM object_values WHERE attrib=? AND source_id=? AND value=?"; arValues.addElement(it->first); arValues.addElement(strSrcID); arValues.addElement(it->second); } } }else { sql = "SELECT object FROM " + src_name; if (hashCond.size() != 0) { sql += " WHERE "; for ( Hashtable<String,String>::iterator it = hashCond.begin(); it != hashCond.end(); ++it ) { if (it != hashCond.begin()) sql += " AND "; sql += it->first + "=?" ; arValues.addElement(it->second); } } } IDBResult res1 = db.executeSQLEx(sql.c_str(), arValues ); if ( nCount == 1 ) { return rhom_load_item_by_object(db, src_name, nSrcID, res1.getStringByIdx(0), isSchemaSrc); } unsigned long items = rho_connectclient_strhasharray_create(); for ( ; !res1.isEnd(); res1.next() ) { rho_connectclient_strhasharray_add(items, rhom_load_item_by_object(db, src_name, nSrcID, res1.getStringByIdx(0), isSchemaSrc) ); } return items; }
virtual void requestBlobsForAttrib(const String& attr, Vector<String>& out ) { IDBResult res = _db.executeSQL( "SELECT value FROM object_values WHERE source_id=? AND attrib=?", _srcID, attr.c_str() ); for ( ;!res.isEnd();res.next()) { out.push_back( /*common::CFilePath::join( RHODESAPP().getBlobsDirPath(), */res.getStringByIdx(0)/*)*/ ); } }
void rho_connectclient_itemdestroy( const char* szModel, unsigned long hash ) { Hashtable<String, String>& hashObject = *((Hashtable<String, String>*)hash); String src_name = szModel; String obj = hashObject.get("object"); String update_type="delete"; IDBResult res = db::CDBAdapter::getUserDB().executeSQL("SELECT source_id, partition, schema, sync_type from sources WHERE name=?", src_name); if ( res.isEnd()) { //TODO: report error - unknown source return; } int nSrcID = res.getIntByIdx(0); String db_partition = res.getStringByIdx(1); bool isSchemaSrc = res.getStringByIdx(2).length() > 0; bool isSyncSrc = res.getStringByIdx(3).compare("none") != 0; String tableName = isSchemaSrc ? src_name : "object_values"; db::CDBAdapter& db = db::CDBAdapter::getDB(db_partition.c_str()); db.startTransaction(); //save list of attrs unsigned long item = 0; if ( isSchemaSrc ) { IDBResult attrsList = db.executeSQL( ("SELECT * FROM " + tableName + " WHERE object=?").c_str(), obj); if ( !attrsList.isEnd() ) item = rhom_make_object(attrsList,nSrcID,isSchemaSrc); }else { IDBResult attrsList = db.executeSQL( ("SELECT attrib, value FROM " + tableName + " WHERE object=? and source_id=?").c_str(), obj, nSrcID); if ( !attrsList.isEnd() ) item = rhom_make_object(attrsList,nSrcID,isSchemaSrc); } //first delete the record from viewable list db.executeSQL( ("DELETE FROM " + tableName + " WHERE object=?").c_str(), obj ); if ( isSyncSrc ) { IDBResult resCreateType = db.executeSQL("SELECT update_type FROM changed_values WHERE object=? and update_type=? and sent=?", obj, "create", 0); db.executeSQL("DELETE FROM changed_values WHERE object=? and sent=?", obj, 0); if ( resCreateType.isEnd() && item != 0 ) { Hashtable<String,String>& hashItem = *((Hashtable<String,String>*)item); for ( Hashtable<String,String>::iterator it = hashItem.begin(); it != hashItem.end(); ++it ) { String key = it->first; String val = it->second; if ( rhom_method_name_isreserved(key) ) continue; Hashtable<String,String> fields; fields.put("source_id", convertToStringA(nSrcID)); fields.put("object", obj); fields.put("attrib", key); fields.put("value", val); fields.put("update_type", update_type); db_insert_into_table(db, "changed_values", fields ); } rho_connectclient_hash_delete(item); } } db.endTransaction(); }
void rho_connectclient_create_object(const char* szModel, unsigned long hash) { Hashtable<String, String>& hashObject = *((Hashtable<String, String>*)hash); String src_name = szModel; IDBResult res = db::CDBAdapter::getUserDB().executeSQL("SELECT source_id, partition, schema, sync_type from sources WHERE name=?", src_name); if ( res.isEnd()) { //TODO: report error - unknown source return; } String update_type = "create"; int nSrcID = res.getIntByIdx(0); String obj = hashObject.containsKey("object") ? hashObject.get("object") : rhom_generate_id(); String db_partition = res.getStringByIdx(1); bool isSchemaSrc = res.getStringByIdx(2).length() > 0; bool isSyncSrc = res.getStringByIdx(3).compare("none") != 0; String tableName = isSchemaSrc ? src_name : "object_values"; db::CDBAdapter& db = db::CDBAdapter::getDB(db_partition.c_str()); hashObject.put("source_id", convertToStringA(nSrcID)); hashObject.put("object", obj); db.startTransaction(); if ( isSyncSrc ) { Hashtable<String,String> fields; fields.put("source_id", convertToStringA(nSrcID)); fields.put("object", obj); fields.put("attrib", "object"); fields.put("update_type", "create"); db_insert_into_table(db, "changed_values", fields ); } if ( isSchemaSrc ) db_insert_into_table(db, tableName, hashObject, "source_id"); else { for ( Hashtable<String,String>::iterator it = hashObject.begin(); it != hashObject.end(); ++it ) { String key = it->first; String val = it->second; if ( rhom_method_name_isreserved(key) ) continue; Hashtable<String,String> fields; fields.put("source_id", convertToStringA(nSrcID)); fields.put("object", obj); fields.put("attrib", key); fields.put("value", val); db_insert_into_table(db, tableName, fields); } } db.endTransaction(); }
void rho_connectclient_save( const char* szModel, unsigned long hash ) { Hashtable<String, String>& hashObject = *((Hashtable<String, String>*)hash); String src_name = szModel; IDBResult res = db::CDBAdapter::getUserDB().executeSQL("SELECT source_id, partition, schema, sync_type from sources WHERE name=?", src_name); if ( res.isEnd()) { //TODO: report error - unknown source return; } int nSrcID = res.getIntByIdx(0); String obj = hashObject.get("object"); String db_partition = res.getStringByIdx(1); bool isSchemaSrc = res.getStringByIdx(2).length() > 0; bool isSyncSrc = res.getStringByIdx(3).compare("none") != 0; String tableName = isSchemaSrc ? src_name : "object_values"; db::CDBAdapter& db = db::CDBAdapter::getDB(db_partition.c_str()); db.startTransaction(); String update_type = ""; String sql; Vector<String> arValues; if (isSchemaSrc) { sql = "SELECT object FROM " + tableName + " WHERE object=? LIMIT 1 OFFSET 0"; arValues.addElement(obj); } else { sql = "SELECT object FROM " + tableName + " WHERE object=? AND source_id=? LIMIT 1 OFFSET 0"; arValues.addElement(obj); arValues.addElement(convertToStringA(nSrcID)); } IDBResult res1 = db.executeSQLEx(sql.c_str(), arValues ); if (!res1.isEnd()) { if (isSyncSrc) { IDBResult resUpdateType = db.executeSQL( "SELECT update_type FROM changed_values WHERE object=? and source_id=? and sent=?", obj, nSrcID, 0 ); if (!resUpdateType.isEnd()) update_type = resUpdateType.getStringByIdx(0); else update_type = "update"; }else update_type = "update"; } else { rho_connectclient_create_object(szModel, hash); } if (!res.isEnd()) { unsigned long item = rhom_load_item_by_object( db, src_name, nSrcID, obj, isSchemaSrc); Hashtable<String, String>& hashItem = *((Hashtable<String, String>*)item); for ( Hashtable<String,String>::iterator it = hashObject.begin(); it != hashObject.end(); ++it ) { String key = it->first; String val = it->second; if ( rhom_method_name_isreserved(key) ) continue; // add rows excluding object, source_id and update_type Hashtable<String,String> fields; fields.put("source_id", convertToStringA(nSrcID)); fields.put("object", obj); fields.put("attrib", key); fields.put("value", val); fields.put("update_type", update_type); if ( db::CDBAdapter::getDB(db_partition.c_str()).getAttrMgr().isBlobAttr(nSrcID, key.c_str()) ) fields.put( "attrib_type", "blob.file"); if ( hashItem.containsKey(key) ) { bool isModified = hashItem.get(key) != val; if (isModified) { if (isSyncSrc) { IDBResult resUpdateType = db.executeSQL( "SELECT update_type FROM changed_values WHERE object=? and attrib=? and source_id=? and sent=?", obj, key, nSrcID, 0 ); if (!resUpdateType.isEnd()) { fields.put("update_type", resUpdateType.getStringByIdx(0) ); db.executeSQL( "DELETE FROM changed_values WHERE object=? and attrib=? and source_id=? and sent=?", obj, key, nSrcID, 0 ); } db_insert_into_table(db, "changed_values", fields); } if ( isSchemaSrc ) db.executeSQL( (String("UPDATE ") + tableName + " SET " + key + "=? WHERE object=?").c_str(), val, obj ); else db.executeSQL( "UPDATE object_values SET value=? WHERE object=? and attrib=? and source_id=?", val, obj, key, nSrcID ); } }else { if (isSyncSrc) db_insert_into_table(db, "changed_values", fields); fields.remove("update_type"); fields.remove("attrib_type"); if (isSchemaSrc) db.executeSQL( (String("UPDATE ") + tableName + " SET " + key + "=? WHERE object=?").c_str(), val, obj ); else db_insert_into_table(db, tableName, fields); } } } db.endTransaction(); }