Exemplo n.º 1
0
void QgsOfflineEditing::committedFeaturesRemoved( const QString& qgisLayerId, const QgsFeatureIds& deletedFeatureIds )
{
  sqlite3* db = openLoggingDb();
  if ( db == NULL )
  {
    return;
  }

  // insert log
  int layerId = getOrCreateLayerId( db, qgisLayerId );

  for ( QgsFeatureIds::const_iterator it = deletedFeatureIds.begin(); it != deletedFeatureIds.end(); ++it )
  {
    if ( isAddedFeature( db, layerId, *it ) )
    {
      // remove from added features log
      QString sql = QString( "DELETE FROM 'log_added_features' WHERE \"layer_id\" = %1 AND \"fid\" = %2" ).arg( layerId ).arg( *it );
      sqlExec( db, sql );
    }
    else
    {
      QString sql = QString( "INSERT INTO 'log_removed_features' VALUES ( %1, %2)" )
                    .arg( layerId )
                    .arg( *it );
      sqlExec( db, sql );
    }
  }

  sqlite3_close( db );
}
Exemplo n.º 2
0
bool Commands::before()
{
	if (!m_mysqlSettings.before.isEmpty())
		return sqlExec(m_mysqlSettings.before);

	return true;
}
Exemplo n.º 3
0
void QgsOfflineEditing::committedGeometriesChanges( const QString& qgisLayerId, const QgsGeometryMap& changedGeometries )
{
  sqlite3* db = openLoggingDb();
  if ( db == NULL )
  {
    return;
  }

  // insert log
  int layerId = getOrCreateLayerId( db, qgisLayerId );
  int commitNo = getCommitNo( db );

  for ( QgsGeometryMap::const_iterator it = changedGeometries.begin(); it != changedGeometries.end(); ++it )
  {
    QgsFeatureId fid = it.key();
    if ( isAddedFeature( db, layerId, fid ) )
    {
      // skip added features
      continue;
    }
    QgsGeometry geom = it.value();
    QString sql = QString( "INSERT INTO 'log_geometry_updates' VALUES ( %1, %2, %3, '%4' )" )
                  .arg( layerId )
                  .arg( commitNo )
                  .arg( fid )
                  .arg( geom.exportToWkt() );
    sqlExec( db, sql );

    // TODO: use WKB instead of WKT?
  }

  increaseCommitNo( db );
  sqlite3_close( db );
}
Exemplo n.º 4
0
static void updateRecord(stKVDatabase *database, int64_t key,
                         const void *value, int64_t sizeOfRecord) {
    MySqlDb *dbImpl = database->dbImpl;
    char *buf = sqlEscape(dbImpl, value, sizeOfRecord);
    sqlExec(dbImpl, "update %s set data=\"%s\" where id=%lld", dbImpl->table, buf,  (long long)key);
    stSafeCFree(buf);
}
Exemplo n.º 5
0
void QgsOfflineEditing::committedFeaturesAdded( const QString& qgisLayerId, const QgsFeatureList& addedFeatures )
{
  sqlite3* db = openLoggingDb();
  if ( db == NULL )
  {
    return;
  }

  // insert log
  int layerId = getOrCreateLayerId( db, qgisLayerId );

  // get new feature ids from db
  QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( qgisLayerId );
  QgsDataSourceURI uri = QgsDataSourceURI( layer->source() );

  // only store feature ids
  QString sql = QString( "SELECT ROWID FROM '%1' ORDER BY ROWID DESC LIMIT %2" ).arg( uri.table() ).arg( addedFeatures.size() );
  QList<int> newFeatureIds = sqlQueryInts( db, sql );
  for ( int i = newFeatureIds.size() - 1; i >= 0; i-- )
  {
    QString sql = QString( "INSERT INTO 'log_added_features' VALUES ( %1, %2 )" )
                  .arg( layerId )
                  .arg( newFeatureIds.at( i ) );
    sqlExec( db, sql );
  }

  sqlite3_close( db );
}
Exemplo n.º 6
0
void QgsOfflineEditing::committedAttributesAdded( const QString& qgisLayerId, const QList<QgsField>& addedAttributes )
{
  sqlite3* db = openLoggingDb();
  if ( db == NULL )
  {
    return;
  }

  // insert log
  int layerId = getOrCreateLayerId( db, qgisLayerId );
  int commitNo = getCommitNo( db );

  for ( QList<QgsField>::const_iterator it = addedAttributes.begin(); it != addedAttributes.end(); ++it )
  {
    QgsField field = *it;
    QString sql = QString( "INSERT INTO 'log_added_attrs' VALUES ( %1, %2, '%3', %4, %5, %6, '%7' )" )
                  .arg( layerId )
                  .arg( commitNo )
                  .arg( field.name() )
                  .arg( field.type() )
                  .arg( field.length() )
                  .arg( field.precision() )
                  .arg( field.comment() );
    sqlExec( db, sql );
  }

  increaseCommitNo( db );
  sqlite3_close( db );
}
Exemplo n.º 7
0
//移出指定组件列表从m_ServiceInfo并删除其数据库ServerDLLInfo里的记录
bool CServiceManage::RemoveDLLCom(CListCtrl *pListCtrl,SC_ServiceInfoStruct *pServiceInfo)
{
	
	if(m_ServiceInfo.IsEmpty())//是否还有记录
	{
		lstrcpy(m_szError,TEXT("组件列表记录里已没有任何组件"));
		return false;
	}
	//搜索要删除的记录
	for(int i=0;i<= m_ServiceInfo.GetUpperBound();i++)
	{
		SC_ServiceInfoStruct* ptem;
		ptem = (SC_ServiceInfoStruct *)(m_ServiceInfo.GetAt(i)); 
		
		//找到记录
		if(ptem->uServiceID == pServiceInfo->uServiceID)
		{

			HANDLE hDatabase=sqlAddConnection("BZGameLocal.bcf");
			if(hDatabase>(HANDLE)0x1000)
			{
				TCHAR szSQL[200];
				wsprintf(szSQL,TEXT("DELETE FROM TGameServerInfo WHERE ServerInfoID = %d"), pServiceInfo->uServiceID);
				sqlExec(hDatabase,szSQL);
			}
			m_ServiceInfo.RemoveAt(i);//同时移出队列中的记录
				pListCtrl->DeleteItem(i);
			return true;
		}
	}
	//没有记录
	lstrcpy(m_szError,TEXT("列表中已无此组件记录"));
	return false;
}
Exemplo n.º 8
0
bool Commands::after()
{
	if (!m_mysqlSettings.after.isEmpty())
		return sqlExec(m_mysqlSettings.after);

	return true;
}
Exemplo n.º 9
0
static void removeRecord(stKVDatabase *database, int64_t key) {
    MySqlDb *dbImpl = database->dbImpl;
    sqlExec(dbImpl, "delete from %s where id=%lld", dbImpl->table, (long long)key);
    my_ulonglong numRows = mysql_affected_rows(dbImpl->conn);
    if (numRows == 0) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "remove of non-existent key %lld", (long long)key);
    } 
}
Exemplo n.º 10
0
void QgsOfflineEditing::createLoggingTables( sqlite3* db )
{
  // indices
  QString sql = "CREATE TABLE 'log_indices' ('name' TEXT, 'last_index' INTEGER)";
  sqlExec( db, sql );

  sql = "INSERT INTO 'log_indices' VALUES ('commit_no', 0)";
  sqlExec( db, sql );

  sql = "INSERT INTO 'log_indices' VALUES ('layer_id', 0)";
  sqlExec( db, sql );

  // layername <-> layer id
  sql = "CREATE TABLE 'log_layer_ids' ('id' INTEGER, 'qgis_id' TEXT)";
  sqlExec( db, sql );

  // offline fid <-> remote fid
  sql = "CREATE TABLE 'log_fids' ('layer_id' INTEGER, 'offline_fid' INTEGER, 'remote_fid' INTEGER)";
  sqlExec( db, sql );

  // added attributes
  sql = "CREATE TABLE 'log_added_attrs' ('layer_id' INTEGER, 'commit_no' INTEGER, ";
  sql += "'name' TEXT, 'type' INTEGER, 'length' INTEGER, 'precision' INTEGER, 'comment' TEXT)";
  sqlExec( db, sql );

  // added features
  sql = "CREATE TABLE 'log_added_features' ('layer_id' INTEGER, 'fid' INTEGER)";
  sqlExec( db, sql );

  // removed features
  sql = "CREATE TABLE 'log_removed_features' ('layer_id' INTEGER, 'fid' INTEGER)";
  sqlExec( db, sql );

  // feature updates
  sql = "CREATE TABLE 'log_feature_updates' ('layer_id' INTEGER, 'commit_no' INTEGER, 'fid' INTEGER, 'attr' INTEGER, 'value' TEXT)";
  sqlExec( db, sql );

  // geometry updates
  sql = "CREATE TABLE 'log_geometry_updates' ('layer_id' INTEGER, 'commit_no' INTEGER, 'fid' INTEGER, 'geom_wkt' TEXT)";
  sqlExec( db, sql );

  /* TODO: other logging tables
    - attr delete (not supported by SpatiaLite provider)
  */
}
Exemplo n.º 11
0
void QgsOfflineEditing::updateFidLookup( QgsVectorLayer* remoteLayer, sqlite3* db, int layerId )
{
  // update fid lookup for added features

  // get remote added fids
  // NOTE: use QMap for sorted fids
  QMap < QgsFeatureId, bool /*dummy*/ > newRemoteFids;
  QgsFeature f;

  QgsFeatureIterator fit = remoteLayer->getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ).setSubsetOfAttributes( QgsAttributeList() ) );

  emit progressModeSet( QgsOfflineEditing::ProcessFeatures, remoteLayer->featureCount() );

  int i = 1;
  while ( fit.nextFeature( f ) )
  {
    if ( offlineFid( db, layerId, f.id() ) == -1 )
    {
      newRemoteFids[ f.id()] = true;
    }

    emit progressUpdated( i++ );
  }

  // get local added fids
  // NOTE: fids are sorted
  QString sql = QString( "SELECT \"fid\" FROM 'log_added_features' WHERE \"layer_id\" = %1" ).arg( layerId );
  QList<int> newOfflineFids = sqlQueryInts( db, sql );

  if ( newRemoteFids.size() != newOfflineFids.size() )
  {
    //showWarning( QString( "Different number of new features on offline layer (%1) and remote layer (%2)" ).arg(newOfflineFids.size()).arg(newRemoteFids.size()) );
  }
  else
  {
    // add new fid lookups
    i = 0;
    sqlExec( db, "BEGIN" );
    for ( QMap<QgsFeatureId, bool>::const_iterator it = newRemoteFids.begin(); it != newRemoteFids.end(); ++it )
    {
      addFidLookup( db, layerId, newOfflineFids.at( i++ ), it.key() );
    }
    sqlExec( db, "COMMIT" );
  }
}
void QgsOfflineEditing::updateFidLookup( QgsVectorLayer* remoteLayer, sqlite3* db, int layerId )
{
  // update fid lookup for added features

  // get remote added fids
  // NOTE: use QMap for sorted fids
  QMap < int, bool /*dummy*/ > newRemoteFids;
  QgsFeature f;
  remoteLayer->select( QgsAttributeList(), QgsRectangle(), false, false );

  mProgressDialog->setupProgressBar( tr( "%v / %m features processed" ), remoteLayer->featureCount() );

  int i = 1;
  while ( remoteLayer->nextFeature( f ) )
  {
    if ( offlineFid( db, layerId, f.id() ) == -1 )
    {
      newRemoteFids[ f.id()] = true;
    }

    mProgressDialog->setProgressValue( i++ );
  }

  // get local added fids
  // NOTE: fids are sorted
  QString sql = QString( "SELECT \"fid\" FROM 'log_added_features' WHERE \"layer_id\" = %1" ).arg( layerId );
  QList<int> newOfflineFids = sqlQueryInts( db, sql );

  if ( newRemoteFids.size() != newOfflineFids.size() )
  {
    //showWarning( QString( "Different number of new features on offline layer (%1) and remote layer (%2)" ).arg(newOfflineFids.size()).arg(newRemoteFids.size()) );
  }
  else
  {
    // add new fid lookups
    i = 0;
    sqlExec( db, "BEGIN" );
    for ( QMap<int, bool>::const_iterator it = newRemoteFids.begin(); it != newRemoteFids.end(); ++it )
    {
      addFidLookup( db, layerId, newOfflineFids.at( i++ ), it.key() );
    }
    sqlExec( db, "COMMIT" );
  }
}
Exemplo n.º 13
0
bool Commands::tag(const Image &img, const Tag &tag, bool after)
{
	QString original = QString(tag.text()).replace(" ", "_");

	QString command = after ? m_commandTagAfter : m_commandTagBefore;
	if (!command.isEmpty())
	{
		Filename fn(command);
		fn.setEscapeMethod(&SqlWorker::escape);
		QStringList execs = fn.path(img, m_profile, QString(), 0, false, false, false, false, true);

		for (QString exec : execs)
		{
			exec.replace("%tag%", original)
				.replace("%original%", tag.text())
				.replace("%type%", tag.type().name())
				.replace("%number%", QString::number(tag.type().number()));

			log(QStringLiteral("Execution of \"%1\"").arg(exec));
			Logger::getInstance().logCommand(exec);

			int code = QProcess::execute(exec);
			if (code != 0)
				log(QStringLiteral("Error executing command (return code: %1)").arg(code));
		}
	}

	QString commandSql = after ? m_mysqlSettings.tagAfter : m_mysqlSettings.tagBefore;
	if (!commandSql.isEmpty())
	{
		start();

		Filename fn(commandSql);
		QStringList execs = fn.path(img, m_profile, QString(), 0, false, false, false, false, true);

		for (QString exec : execs)
		{
			exec.replace("%tag%", m_sqlWorker->escape(original))
				.replace("%original%", m_sqlWorker->escape(tag.text()))
				.replace("%type%", m_sqlWorker->escape(tag.type().name()))
				.replace("%number%", QString::number(tag.type().number()));

			if (!sqlExec(exec))
				return false;
		}
	}

	return true;
}
Exemplo n.º 14
0
int QgsOfflineEditing::getOrCreateLayerId( sqlite3* db, const QString& qgisLayerId )
{
  QString sql = QString( "SELECT \"id\" FROM 'log_layer_ids' WHERE \"qgis_id\" = '%1'" ).arg( qgisLayerId );
  int layerId = sqlQueryInt( db, sql, -1 );
  if ( layerId == -1 )
  {
    // next layer id
    sql = "SELECT \"last_index\" FROM 'log_indices' WHERE \"name\" = 'layer_id'";
    int newLayerId = sqlQueryInt( db, sql, -1 );

    // insert layer
    sql = QString( "INSERT INTO 'log_layer_ids' VALUES (%1, '%2')" ).arg( newLayerId ).arg( qgisLayerId );
    sqlExec( db, sql );

    // increase layer_id
    // TODO: use trigger for auto increment?
    sql = QString( "UPDATE 'log_indices' SET 'last_index' = %1 WHERE \"name\" = 'layer_id'" ).arg( newLayerId + 1 );
    sqlExec( db, sql );

    layerId = newLayerId;
  }

  return layerId;
}
Exemplo n.º 15
0
bool Commands::image(const Image &img, const QString &path)
{
	// Normal commands
	if (!m_commandImage.isEmpty())
	{
		Filename fn(m_commandImage);
		QStringList execs = fn.path(img, m_profile, QString(), 0, false, false, false, false);

		for (QString exec : execs)
		{
			exec.replace("%path:nobackslash%", QDir::toNativeSeparators(path).replace("\\", "/"))
				.replace("%path%", QDir::toNativeSeparators(path));

			log(QStringLiteral("Execution of \"%1\"").arg(exec));
			Logger::getInstance().logCommand(exec);

			int code = QProcess::execute(exec);
			if (code != 0)
				log(QStringLiteral("Error executing command (return code: %1)").arg(code));
		}
	}

	// SQL commands
	if (!m_mysqlSettings.image.isEmpty())
	{
		Filename fn(m_mysqlSettings.image);
		fn.setEscapeMethod(&SqlWorker::escape);
		QStringList execs = fn.path(img, m_profile, QString(), 0, false, false, false, false);

		for (QString exec : execs)
		{
			exec.replace("%path:nobackslash%", m_sqlWorker->escape(QDir::toNativeSeparators(path).replace("\\", "/")))
				.replace("%path%", m_sqlWorker->escape(QDir::toNativeSeparators(path)));

			if (!sqlExec(exec))
				return false;
		}
	}

	return true;
}
Exemplo n.º 16
0
void QgsOfflineEditing::committedAttributeValuesChanges( const QString& qgisLayerId, const QgsChangedAttributesMap& changedAttrsMap )
{
  sqlite3* db = openLoggingDb();
  if ( db == NULL )
  {
    return;
  }

  // insert log
  int layerId = getOrCreateLayerId( db, qgisLayerId );
  int commitNo = getCommitNo( db );

  for ( QgsChangedAttributesMap::const_iterator cit = changedAttrsMap.begin(); cit != changedAttrsMap.end(); ++cit )
  {
    QgsFeatureId fid = cit.key();
    if ( isAddedFeature( db, layerId, fid ) )
    {
      // skip added features
      continue;
    }
    QgsAttributeMap attrMap = cit.value();
    for ( QgsAttributeMap::const_iterator it = attrMap.begin(); it != attrMap.end(); ++it )
    {
      QString sql = QString( "INSERT INTO 'log_feature_updates' VALUES ( %1, %2, %3, %4, '%5' )" )
                    .arg( layerId )
                    .arg( commitNo )
                    .arg( fid )
                    .arg( it.key() ) // attr
                    .arg( it.value().toString() ); // value
      sqlExec( db, sql );
    }
  }

  increaseCommitNo( db );
  sqlite3_close( db );
}
Exemplo n.º 17
0
/* connect to a database server */
static MySqlDb *connect(stKVDatabaseConf *conf) {
    MySqlDb *dbImpl = stSafeCCalloc(sizeof(MySqlDb));
    if ((dbImpl->conn = mysql_init(NULL)) == NULL) {
        disconnect(dbImpl);
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "mysql_init failed");
    }
    if (mysql_real_connect(dbImpl->conn, stKVDatabaseConf_getHost(conf), stKVDatabaseConf_getUser(conf), stKVDatabaseConf_getPassword(conf), stKVDatabaseConf_getDatabaseName(conf), stKVDatabaseConf_getPort(conf), NULL, 0) == NULL) {
        stExcept *ex = createMySqlExcept(dbImpl, "failed to connect to MySql database: %s on %s as user %s",
                                         stKVDatabaseConf_getDatabaseName(conf), stKVDatabaseConf_getHost(conf), stKVDatabaseConf_getUser(conf));
        disconnect(dbImpl);
        stThrow(ex);
    }
    dbImpl->table = stString_copy(stKVDatabaseConf_getTableName(conf));

    // disable report of notes, so only warnings and errors come back
    sqlExec(dbImpl, "set sql_notes=0");

    // set max sizes of an sql statment to 1G.  This must also be specified
    // for the server by adding "max_allowed_packet = 1G" to the [mysqld]
    // section of my.cnf
    sqlExec(dbImpl, "set global max_allowed_packet=1073741824");

    // set the idle timeout to a week
    int waitTimeout = 7 * 24 * 60 * 60;  // 1 week
    sqlExec(dbImpl, "set wait_timeout=%d", waitTimeout);

    // set the read timeout to an hour
    int readTimeout = 60 * 60;  // 1 hour
    sqlExec(dbImpl, "set net_read_timeout=%d", readTimeout);

    // NOTE: commit will not return an error, this does row-level locking on
    // the select done before the update
    sqlExec(dbImpl, "set autocommit = 0;");
    sqlExec(dbImpl, "set session transaction isolation level serializable;");
    return dbImpl;
}
Exemplo n.º 18
0
static void commitTransaction(stKVDatabase *database) {
    MySqlDb *dbImpl = database->dbImpl;
    sqlExec(dbImpl, "commit;");
}
Exemplo n.º 19
0
void QgsOfflineEditing::increaseCommitNo( sqlite3* db )
{
  QString sql = QString( "UPDATE 'log_indices' SET 'last_index' = %1 WHERE \"name\" = 'commit_no'" ).arg( getCommitNo( db ) + 1 );
  sqlExec( db, sql );
}
Exemplo n.º 20
0
static void startTransaction(stKVDatabase *database) {
    MySqlDb *dbImpl = database->dbImpl;
    sqlExec(dbImpl, "start transaction with consistent snapshot;");
}
Exemplo n.º 21
0
static void insertInt64(stKVDatabase *database, int64_t key, int64_t value) {
    MySqlDb *dbImpl = database->dbImpl;
    char *buf = sqlEscape(dbImpl, &value, sizeof(int64_t));
    sqlExec(dbImpl, "insert into %s (id, data) values (%lld, \"%s\")", dbImpl->table, (long long)key, buf);
}
Exemplo n.º 22
0
static void insertRecord(stKVDatabase *database, int64_t key, const void *value, int64_t sizeOfRecord) {
    MySqlDb *dbImpl = database->dbImpl;
    char *buf = sqlEscape(dbImpl, value, sizeOfRecord);
    sqlExec(dbImpl, "insert into %s (id, data) values (%lld, \"%s\")", dbImpl->table, (long long)key, buf);
    stSafeCFree(buf);
}
Exemplo n.º 23
0
static void updateInt64(stKVDatabase *database, int64_t key, int64_t value) {
    MySqlDb *dbImpl = database->dbImpl;
    char *buf = sqlEscape(dbImpl, &value, sizeof(int64_t));
    sqlExec(dbImpl, "update %s set data=\"%s\" where id=%lld", dbImpl->table, buf,  (long long)key);
}
Exemplo n.º 24
0
static void deleteDB(stKVDatabase *database) {
    MySqlDb *dbImpl = database->dbImpl;
    sqlExec(dbImpl, "drop table %s", dbImpl->table);
    destructDB(database);
}
Exemplo n.º 25
0
void QgsOfflineEditing::addFidLookup( sqlite3* db, int layerId, QgsFeatureId offlineFid, QgsFeatureId remoteFid )
{
  QString sql = QString( "INSERT INTO 'log_fids' VALUES ( %1, %2, %3 )" ).arg( layerId ).arg( offlineFid ).arg( remoteFid );
  sqlExec( db, sql );
}
Exemplo n.º 26
0
static void abortTransaction(stKVDatabase *database) {
    MySqlDb *dbImpl = database->dbImpl;
    sqlExec(dbImpl, "rollback;");
}
Exemplo n.º 27
0
void QgsOfflineEditing::synchronize()
{
  // open logging db
  sqlite3* db = openLoggingDb();
  if ( db == NULL )
  {
    return;
  }

  emit progressStarted();

  // restore and sync remote layers
  QList<QgsMapLayer*> offlineLayers;
  QMap<QString, QgsMapLayer*> mapLayers = QgsMapLayerRegistry::instance()->mapLayers();
  for ( QMap<QString, QgsMapLayer*>::iterator layer_it = mapLayers.begin() ; layer_it != mapLayers.end(); ++layer_it )
  {
    QgsMapLayer* layer = layer_it.value();
    if ( layer->customProperty( CUSTOM_PROPERTY_IS_OFFLINE_EDITABLE, false ).toBool() )
    {
      offlineLayers << layer;
    }
  }

  for ( int l = 0; l < offlineLayers.count(); l++ )
  {
    QgsMapLayer* layer = offlineLayers[l];

    emit layerProgressUpdated( l + 1, offlineLayers.count() );

    QString remoteSource = layer->customProperty( CUSTOM_PROPERTY_REMOTE_SOURCE, "" ).toString();
    QString remoteProvider = layer->customProperty( CUSTOM_PROPERTY_REMOTE_PROVIDER, "" ).toString();
    QString remoteName = layer->name();
    remoteName.remove( QRegExp( " \\(offline\\)$" ) );

    QgsVectorLayer* remoteLayer = new QgsVectorLayer( remoteSource, remoteName, remoteProvider );
    if ( remoteLayer->isValid() )
    {
      // TODO: only add remote layer if there are log entries?

      QgsVectorLayer* offlineLayer = qobject_cast<QgsVectorLayer*>( layer );

      // copy style
      copySymbology( offlineLayer, remoteLayer );

      // register this layer with the central layers registry
      QgsMapLayerRegistry::instance()->addMapLayers(
        QList<QgsMapLayer *>() << remoteLayer, true );

      // apply layer edit log
      QString qgisLayerId = layer->id();
      QString sql = QString( "SELECT \"id\" FROM 'log_layer_ids' WHERE \"qgis_id\" = '%1'" ).arg( qgisLayerId );
      int layerId = sqlQueryInt( db, sql, -1 );
      if ( layerId != -1 )
      {
        remoteLayer->startEditing();

        // TODO: only get commitNos of this layer?
        int commitNo = getCommitNo( db );
        for ( int i = 0; i < commitNo; i++ )
        {
          // apply commits chronologically
          applyAttributesAdded( remoteLayer, db, layerId, i );
          applyAttributeValueChanges( offlineLayer, remoteLayer, db, layerId, i );
          applyGeometryChanges( remoteLayer, db, layerId, i );
        }

        applyFeaturesAdded( offlineLayer, remoteLayer, db, layerId );
        applyFeaturesRemoved( remoteLayer, db, layerId );

        if ( remoteLayer->commitChanges() )
        {
          // update fid lookup
          updateFidLookup( remoteLayer, db, layerId );

          // clear edit log for this layer
          sql = QString( "DELETE FROM 'log_added_attrs' WHERE \"layer_id\" = %1" ).arg( layerId );
          sqlExec( db, sql );
          sql = QString( "DELETE FROM 'log_added_features' WHERE \"layer_id\" = %1" ).arg( layerId );
          sqlExec( db, sql );
          sql = QString( "DELETE FROM 'log_removed_features' WHERE \"layer_id\" = %1" ).arg( layerId );
          sqlExec( db, sql );
          sql = QString( "DELETE FROM 'log_feature_updates' WHERE \"layer_id\" = %1" ).arg( layerId );
          sqlExec( db, sql );
          sql = QString( "DELETE FROM 'log_geometry_updates' WHERE \"layer_id\" = %1" ).arg( layerId );
          sqlExec( db, sql );

          // reset commitNo
          QString sql = QString( "UPDATE 'log_indices' SET 'last_index' = 0 WHERE \"name\" = 'commit_no'" );
          sqlExec( db, sql );
        }
        else
        {
          showWarning( remoteLayer->commitErrors().join( "\n" ) );
        }
      }

      // remove offline layer
      QgsMapLayerRegistry::instance()->removeMapLayers(
        ( QStringList() << qgisLayerId ) );

      // disable offline project
      QString projectTitle = QgsProject::instance()->title();
      projectTitle.remove( QRegExp( " \\(offline\\)$" ) );
      QgsProject::instance()->title( projectTitle );
      QgsProject::instance()->removeEntry( PROJECT_ENTRY_SCOPE_OFFLINE, PROJECT_ENTRY_KEY_OFFLINE_DB_PATH );
      remoteLayer->reload(); //update with other changes
    }
  }

  emit progressStopped();

  sqlite3_close( db );
}
Exemplo n.º 28
0
/* create the keyword/value table */
static void createKVTable(MySqlDb *dbImpl) {
    sqlExec(dbImpl, "drop table if exists %s", dbImpl->table);
    sqlExec(dbImpl, "create table %s (id bigint primary key, data longblob) engine=INNODB;", dbImpl->table);
}
Exemplo n.º 29
0
void QgsOfflineEditing::copyVectorLayer( QgsVectorLayer* layer, sqlite3* db, const QString& offlineDbPath )
{
  if ( layer == NULL )
  {
    return;
  }

  QString tableName = layer->name();

  // create table
  QString sql = QString( "CREATE TABLE '%1' (" ).arg( tableName );
  QString delim = "";
  const QgsFields& fields = layer->dataProvider()->fields();
  for ( int idx = 0; idx < fields.count(); ++idx )
  {
    QString dataType = "";
    QVariant::Type type = fields[idx].type();
    if ( type == QVariant::Int )
    {
      dataType = "INTEGER";
    }
    else if ( type == QVariant::Double )
    {
      dataType = "REAL";
    }
    else if ( type == QVariant::String )
    {
      dataType = "TEXT";
    }
    else
    {
      showWarning( tr( "Unknown data type %1" ).arg( type ) );
    }

    sql += delim + QString( "'%1' %2" ).arg( fields[idx].name() ).arg( dataType );
    delim = ",";
  }
  sql += ")";

  // add geometry column
  QString geomType = "";
  switch ( layer->wkbType() )
  {
    case QGis::WKBPoint:
      geomType = "POINT";
      break;
    case QGis::WKBMultiPoint:
      geomType = "MULTIPOINT";
      break;
    case QGis::WKBLineString:
      geomType = "LINESTRING";
      break;
    case QGis::WKBMultiLineString:
      geomType = "MULTILINESTRING";
      break;
    case QGis::WKBPolygon:
      geomType = "POLYGON";
      break;
    case QGis::WKBMultiPolygon:
      geomType = "MULTIPOLYGON";
      break;
    default:
      showWarning( tr( "QGIS wkbType %1 not supported" ).arg( layer->wkbType() ) );
      break;
  };
  QString sqlAddGeom = QString( "SELECT AddGeometryColumn('%1', 'Geometry', %2, '%3', 2)" )
                       .arg( tableName )
                       .arg( layer->crs().authid().startsWith( "EPSG:", Qt::CaseInsensitive ) ? layer->crs().authid().mid( 5 ).toLong() : 0 )
                       .arg( geomType );

  // create spatial index
  QString sqlCreateIndex = QString( "SELECT CreateSpatialIndex('%1', 'Geometry')" ).arg( tableName );

  int rc = sqlExec( db, sql );
  if ( rc == SQLITE_OK )
  {
    rc = sqlExec( db, sqlAddGeom );
    if ( rc == SQLITE_OK )
    {
      rc = sqlExec( db, sqlCreateIndex );
    }
  }

  if ( rc == SQLITE_OK )
  {
    // add new layer
    QgsVectorLayer* newLayer = new QgsVectorLayer( QString( "dbname='%1' table='%2'(Geometry) sql=" )
        .arg( offlineDbPath ).arg( tableName ), tableName + " (offline)", "spatialite" );
    if ( newLayer->isValid() )
    {
      // mark as offline layer
      newLayer->setCustomProperty( CUSTOM_PROPERTY_IS_OFFLINE_EDITABLE, true );

      // store original layer source
      newLayer->setCustomProperty( CUSTOM_PROPERTY_REMOTE_SOURCE, layer->source() );
      newLayer->setCustomProperty( CUSTOM_PROPERTY_REMOTE_PROVIDER, layer->providerType() );

      // copy style
      bool hasLabels = layer->hasLabelsEnabled();
      if ( !hasLabels )
      {
        // NOTE: copy symbology before adding the layer so it is displayed correctly
        copySymbology( layer, newLayer );
      }

      // register this layer with the central layers registry
      QgsMapLayerRegistry::instance()->addMapLayers(
        QList<QgsMapLayer *>() << newLayer );

      if ( hasLabels )
      {
        // NOTE: copy symbology of layers with labels enabled after adding to project, as it will crash otherwise (WORKAROUND)
        copySymbology( layer, newLayer );
      }

      // TODO: layer order

      // copy features
      newLayer->startEditing();
      QgsFeature f;

      // NOTE: force feature recount for PostGIS layer, else only visible features are counted, before iterating over all features (WORKAROUND)
      layer->setSubsetString( "" );

      QgsFeatureIterator fit = layer->getFeatures();

      emit progressModeSet( QgsOfflineEditing::CopyFeatures, layer->featureCount() );
      int featureCount = 1;

      QList<QgsFeatureId> remoteFeatureIds;
      while ( fit.nextFeature( f ) )
      {
        remoteFeatureIds << f.id();

        // NOTE: Spatialite provider ignores position of geometry column
        // fill gap in QgsAttributeMap if geometry column is not last (WORKAROUND)
        int column = 0;
        QgsAttributes attrs = f.attributes();
        QgsAttributes newAttrs( attrs.count() );
        for ( int it = 0; it < attrs.count(); ++it )
        {
          newAttrs[column++] = attrs[it];
        }
        f.setAttributes( newAttrs );

        newLayer->addFeature( f, false );

        emit progressUpdated( featureCount++ );
      }
      if ( newLayer->commitChanges() )
      {
        emit progressModeSet( QgsOfflineEditing::ProcessFeatures, layer->featureCount() );
        featureCount = 1;

        // update feature id lookup
        int layerId = getOrCreateLayerId( db, newLayer->id() );
        QList<QgsFeatureId> offlineFeatureIds;

        QgsFeatureIterator fit = newLayer->getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ).setSubsetOfAttributes( QgsAttributeList() ) );
        while ( fit.nextFeature( f ) )
        {
          offlineFeatureIds << f.id();
        }

        // NOTE: insert fids in this loop, as the db is locked during newLayer->nextFeature()
        sqlExec( db, "BEGIN" );
        int remoteCount = remoteFeatureIds.size();
        for ( int i = 0; i < remoteCount; i++ )
        {
          addFidLookup( db, layerId, offlineFeatureIds.at( i ), remoteFeatureIds.at( remoteCount - ( i + 1 ) ) );
          emit progressUpdated( featureCount++ );
        }
        sqlExec( db, "COMMIT" );
      }
      else
      {
        showWarning( newLayer->commitErrors().join( "\n" ) );
      }

      // remove remote layer
      QgsMapLayerRegistry::instance()->removeMapLayers(
        QStringList() << layer->id() );
    }
  }
}