""" *************************************************************************** PostGISExecuteAndLoadSQL.py --------------------- Date : May 2018 Copyright : (C) 2018 by Anita Graser Email : anitagraser at gmx dot at --------------------- based on PostGISExecuteSQL.py by Victor Olaya and Carterix Geomatics *************************************************************************** * * * 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__ = "Anita Graser" __date__ = "May 2018" __copyright__ = "(C) 2018, Anita Graser" from qgis.core import ( QgsProcessingException, QgsProcessingParameterString, QgsVectorLayer, QgsDataSourceUri, QgsProcessing, QgsProcessingOutputVectorLayer, QgsProcessingContext, QgsProcessingParameterProviderConnection, QgsProviderRegistry, QgsProviderConnectionException, QgsProcessingAlgorithm, ) from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm class PostGISExecuteAndLoadSQL(QgisAlgorithm): DATABASE = "DATABASE" SQL = "SQL" OUTPUT = "OUTPUT" ID_FIELD = "ID_FIELD" GEOMETRY_FIELD = "GEOMETRY_FIELD" def group(self): return self.tr("Database") def groupId(self): return "database" def __init__(self): super().__init__() def flags(self): return ( super().flags() | QgsProcessingAlgorithm.Flag.FlagNotAvailableInStandaloneTool | QgsProcessingAlgorithm.Flag.FlagRequiresProject ) def initAlgorithm(self, config=None): db_param = QgsProcessingParameterProviderConnection( self.DATABASE, self.tr("Database (connection name)"), "postgres" ) self.addParameter(db_param) self.addParameter( QgsProcessingParameterString(self.SQL, self.tr("SQL query"), multiLine=True) ) self.addParameter( QgsProcessingParameterString( self.ID_FIELD, self.tr("Unique ID field name"), defaultValue="id" ) ) self.addParameter( QgsProcessingParameterString( self.GEOMETRY_FIELD, self.tr("Geometry field name"), defaultValue="geom", optional=True, ) ) self.addOutput( QgsProcessingOutputVectorLayer( self.OUTPUT, self.tr("Output layer"), QgsProcessing.SourceType.TypeVectorAnyGeometry, ) ) def name(self): return "postgisexecuteandloadsql" def displayName(self): return self.tr("PostgreSQL execute and load SQL") def shortDescription(self): return self.tr( "Executes a SQL command on a PostgreSQL database and loads the result as a table" ) def tags(self): return self.tr("postgis,table,database").split(",") def processAlgorithm(self, parameters, context, feedback): connection_name = self.parameterAsConnectionName( parameters, self.DATABASE, context ) id_field = self.parameterAsString(parameters, self.ID_FIELD, context) geom_field = self.parameterAsString(parameters, self.GEOMETRY_FIELD, context) # resolve connection details to uri try: md = QgsProviderRegistry.instance().providerMetadata("postgres") conn = md.createConnection(connection_name) except QgsProviderConnectionException: raise QgsProcessingException( self.tr("Could not retrieve connection details for {}").format( connection_name ) ) uri = QgsDataSourceUri(conn.uri()) sql = self.parameterAsString(parameters, self.SQL, context) sql = sql.replace("\n", " ") uri.setDataSource("", "(" + sql.rstrip(";") + ")", geom_field, "", id_field) vlayer = QgsVectorLayer(uri.uri(), "layername", "postgres") if not vlayer.isValid(): raise QgsProcessingException( self.tr( """This layer is invalid! Please check the PostGIS log for error messages.""" ) ) context.temporaryLayerStore().addMapLayer(vlayer) context.addLayerToLoadOnCompletion( vlayer.id(), QgsProcessingContext.LayerDetails( "SQL layer", context.project(), self.OUTPUT ), ) return {self.OUTPUT: vlayer.id()}