示例#1
0
		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)/*)*/ );
			}
		}
示例#2
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;
}
示例#3
0
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;
}
示例#5
0
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();
}
示例#6
0
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);
}
示例#7
0
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);
    }
}
示例#8
0
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;
}
示例#9
0
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;
}
示例#10
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;

}
示例#11
0
/*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);
    }
}
示例#12
0
	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;
	}
示例#13
0
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);
        }
    }
}
示例#14
0
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;
}
示例#15
0
		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)/*)*/ );
			}
		}
示例#16
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();
}
示例#17
0
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();
}
示例#18
0
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();
}