From c0e81783669fc6d67f22828423a179e2bc9b3982 Mon Sep 17 00:00:00 2001 From: Alexander Bruy Date: Mon, 11 May 2020 13:11:28 +0300 Subject: [PATCH] [processing] port SpatiaLite Execute SQL algorithm to C++ --- .../algs/qgis/QgisAlgorithmProvider.py | 2 - .../algs/qgis/SpatialiteExecuteSQL.py | 88 ----------------- src/analysis/CMakeLists.txt | 1 + .../qgsalgorithmexecutespatialitequery.cpp | 96 +++++++++++++++++++ .../qgsalgorithmexecutespatialitequery.h | 54 +++++++++++ .../processing/qgsnativealgorithms.cpp | 2 + 6 files changed, 153 insertions(+), 90 deletions(-) delete mode 100644 python/plugins/processing/algs/qgis/SpatialiteExecuteSQL.py create mode 100644 src/analysis/processing/qgsalgorithmexecutespatialitequery.cpp create mode 100644 src/analysis/processing/qgsalgorithmexecutespatialitequery.h diff --git a/python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py b/python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py index 096833bffe5..55bf54d7b6e 100644 --- a/python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py +++ b/python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py @@ -82,7 +82,6 @@ from .SelectByExpression import SelectByExpression from .SetRasterStyle import SetRasterStyle from .SetVectorStyle import SetVectorStyle from .SnapGeometries import SnapGeometriesToLayer -from .SpatialiteExecuteSQL import SpatialiteExecuteSQL from .SpatialJoinSummary import SpatialJoinSummary from .StatisticsByCategories import StatisticsByCategories from .TextToFloat import TextToFloat @@ -161,7 +160,6 @@ class QgisAlgorithmProvider(QgsProcessingProvider): SetRasterStyle(), SetVectorStyle(), SnapGeometriesToLayer(), - SpatialiteExecuteSQL(), SpatialJoinSummary(), StatisticsByCategories(), TextToFloat(), diff --git a/python/plugins/processing/algs/qgis/SpatialiteExecuteSQL.py b/python/plugins/processing/algs/qgis/SpatialiteExecuteSQL.py deleted file mode 100644 index 9bf227fe137..00000000000 --- a/python/plugins/processing/algs/qgis/SpatialiteExecuteSQL.py +++ /dev/null @@ -1,88 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -*************************************************************************** - SpatialiteExecuteSQL.py - --------------------- - Date : October 2016 - Copyright : (C) 2016 by Mathieu Pellerin - Email : nirvn dot asia at gmail dot com -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -*************************************************************************** -""" - -__author__ = 'Mathieu Pellerin' -__date__ = 'October 2016' -__copyright__ = '(C) 2016, Mathieu Pellerin' - -from qgis.core import (QgsDataSourceUri, - QgsProcessing, - QgsProcessingAlgorithm, - QgsProcessingException, - QgsProcessingParameterVectorLayer, - QgsProcessingParameterString, - QgsProviderRegistry, - QgsProviderConnectionException) - -from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm - - -class SpatialiteExecuteSQL(QgisAlgorithm): - DATABASE = 'DATABASE' - SQL = 'SQL' - - def group(self): - return self.tr('Database') - - def groupId(self): - return 'database' - - def __init__(self): - super().__init__() - - def initAlgorithm(self, config=None): - self.addParameter(QgsProcessingParameterVectorLayer(self.DATABASE, self.tr('File Database'), types=[QgsProcessing.TypeVector], optional=False)) - self.addParameter(QgsProcessingParameterString(self.SQL, self.tr('SQL query'), multiLine=True)) - - def name(self): - return 'spatialiteexecutesql' - - def displayName(self): - return self.tr('SpatiaLite execute SQL') - - def shortDescription(self): - return self.tr('Executes a SQL command on a SpatiaLite database') - - def flags(self): - return super().flags() | QgsProcessingAlgorithm.FlagNoThreading - - def processAlgorithm(self, parameters, context, feedback): - database = self.parameterAsVectorLayer(parameters, self.DATABASE, context) - databaseuri = database.dataProvider().dataSourceUri() - uri = QgsDataSourceUri(databaseuri) - if uri.database() == '': - if '|layername' in databaseuri: - databaseuri = databaseuri[:databaseuri.find('|layername')] - elif '|layerid' in databaseuri: - databaseuri = databaseuri[:databaseuri.find('|layerid')] - uri = QgsDataSourceUri('dbname=\'%s\'' % (databaseuri)) - - try: - md = QgsProviderRegistry.instance().providerMetadata('spatialite') - conn = md.createConnection(uri.uri(), {}) - except QgsProviderConnectionException: - raise QgsProcessingException(self.tr('Could not connect to {}').format(uri.uri())) - - sql = self.parameterAsString(parameters, self.SQL, context).replace('\n', ' ') - try: - conn.executeSql(sql) - except QgsProviderConnectionException as e: - raise QgsProcessingException(self.tr('Error executing SQL:\n{0}').format(e)) - - return {} diff --git a/src/analysis/CMakeLists.txt b/src/analysis/CMakeLists.txt index 814ca8a1b3a..a8327ed982f 100644 --- a/src/analysis/CMakeLists.txt +++ b/src/analysis/CMakeLists.txt @@ -51,6 +51,7 @@ SET(QGIS_ANALYSIS_SRCS processing/qgsalgorithmdropgeometry.cpp processing/qgsalgorithmdropmzvalues.cpp processing/qgsalgorithmexecutepostgisquery.cpp + processing/qgsalgorithmexecutespatialitequery.cpp processing/qgsalgorithmexplode.cpp processing/qgsalgorithmexplodehstore.cpp processing/qgsalgorithmextendlines.cpp diff --git a/src/analysis/processing/qgsalgorithmexecutespatialitequery.cpp b/src/analysis/processing/qgsalgorithmexecutespatialitequery.cpp new file mode 100644 index 00000000000..eef7fb7a5dc --- /dev/null +++ b/src/analysis/processing/qgsalgorithmexecutespatialitequery.cpp @@ -0,0 +1,96 @@ +/*************************************************************************** + qgsalgorithmexecutepostgisquery.cpp + --------------------- + begin : May 2020 + copyright : (C) 2020 by Alexander Bruy + email : alexander dot bruy at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgsalgorithmexecutespatialitequery.h" +#include "qgsproviderregistry.h" +#include "qgsprovidermetadata.h" +#include "qgsabstractdatabaseproviderconnection.h" + +///@cond PRIVATE + +QString QgsExecuteSpatialiteQueryAlgorithm::name() const +{ + return QStringLiteral( "spatialiteexecutesql" ); +} + +QString QgsExecuteSpatialiteQueryAlgorithm::displayName() const +{ + return QObject::tr( "SpatiaLite execute SQL" ); +} + +QStringList QgsExecuteSpatialiteQueryAlgorithm::tags() const +{ + return QObject::tr( "database,sql,spatialite,execute" ).split( ',' ); +} + +QString QgsExecuteSpatialiteQueryAlgorithm::group() const +{ + return QObject::tr( "Database" ); +} + +QString QgsExecuteSpatialiteQueryAlgorithm::groupId() const +{ + return QStringLiteral( "database" ); +} + +QString QgsExecuteSpatialiteQueryAlgorithm::shortHelpString() const +{ + return QObject::tr( "Executes a SQL command on a SpatiaLite database." ); +} + +QgsExecuteSpatialiteQueryAlgorithm *QgsExecuteSpatialiteQueryAlgorithm::createInstance() const +{ + return new QgsExecuteSpatialiteQueryAlgorithm(); +} + +void QgsExecuteSpatialiteQueryAlgorithm::initAlgorithm( const QVariantMap & ) +{ + addParameter( new QgsProcessingParameterProviderConnection( QStringLiteral( "DATABASE" ), QObject::tr( "Database (connection name)" ), QStringLiteral( "spatialite" ) ) ); + addParameter( new QgsProcessingParameterString( QStringLiteral( "SQL" ), QObject::tr( "SQL query" ), QVariant(), true ) ); +} + +QVariantMap QgsExecuteSpatialiteQueryAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) +{ + Q_UNUSED( feedback ); + + QString connName = parameterAsConnectionName( parameters, QStringLiteral( "DATABASE" ), context ); + + std::unique_ptr conn; + try + { + std::unique_ptr md( QgsProviderRegistry::instance()->providerMetadata( QStringLiteral( "spatialite" ) ) ); + conn.reset( static_cast( md->createConnection( connName ) ) ); + } + catch ( QgsProviderConnectionException & ) + { + throw QgsProcessingException( QObject::tr( "Could not retrieve connection details for %1" ).arg( connName ) ); + } + + QString sql = parameterAsString( parameters, QStringLiteral( "SQL" ), context ).replace( '\n', ' ' ); + try + { + conn->executeSql( sql ); + } + catch ( QgsProviderConnectionException &ex ) + { + throw QgsProcessingException( QObject::tr( "Error executing SQL:\n%1" ).arg( ex.what() ) ); + } + + return QVariantMap(); +} + +///@endcond diff --git a/src/analysis/processing/qgsalgorithmexecutespatialitequery.h b/src/analysis/processing/qgsalgorithmexecutespatialitequery.h new file mode 100644 index 00000000000..b9e205f55c6 --- /dev/null +++ b/src/analysis/processing/qgsalgorithmexecutespatialitequery.h @@ -0,0 +1,54 @@ +/*************************************************************************** + qgsalgorithmexecutespatialitequery.h + ------------------------------ + begin : May 2020 + copyright : (C) 2020 by Alexander Bruy + email : alexander dot bruy at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSALGORITHMEXECUTESPATIALITEQUERY_H +#define QGSALGORITHMEXECUTESPATIALITEQUERY_H + +#define SIP_NO_FILE + +#include "qgis_sip.h" +#include "qgsprocessingalgorithm.h" + +///@cond PRIVATE + +/** + * Native execute PostGIS query algorithm. + */ +class QgsExecuteSpatialiteQueryAlgorithm : public QgsProcessingAlgorithm +{ + + public: + + QgsExecuteSpatialiteQueryAlgorithm() = default; + void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override; + QString name() const override; + QString displayName() const override; + QStringList tags() const override; + QString group() const override; + QString groupId() const override; + QString shortHelpString() const override; + QgsExecuteSpatialiteQueryAlgorithm *createInstance() const override SIP_FACTORY; + + protected: + + QVariantMap processAlgorithm( const QVariantMap ¶meters, + QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override; +}; + +///@endcond PRIVATE + +#endif // QGSALGORITHMEXECUTESPATIALITEQUERY_H diff --git a/src/analysis/processing/qgsnativealgorithms.cpp b/src/analysis/processing/qgsnativealgorithms.cpp index fefe3149431..6774351825e 100644 --- a/src/analysis/processing/qgsnativealgorithms.cpp +++ b/src/analysis/processing/qgsnativealgorithms.cpp @@ -46,6 +46,7 @@ #include "qgsalgorithmdropgeometry.h" #include "qgsalgorithmdropmzvalues.h" #include "qgsalgorithmexecutepostgisquery.h" +#include "qgsalgorithmexecutespatialitequery.h" #include "qgsalgorithmexplode.h" #include "qgsalgorithmexplodehstore.h" #include "qgsalgorithmextendlines.h" @@ -245,6 +246,7 @@ void QgsNativeAlgorithms::loadAlgorithms() addAlgorithm( new QgsDropGeometryAlgorithm() ); addAlgorithm( new QgsDropMZValuesAlgorithm() ); addAlgorithm( new QgsExecutePostgisQueryAlgorithm() ); + addAlgorithm( new QgsExecuteSpatialiteQueryAlgorithm() ); addAlgorithm( new QgsExplodeAlgorithm() ); addAlgorithm( new QgsExplodeHstoreAlgorithm() ); addAlgorithm( new QgsExtendLinesAlgorithm() );