27using namespace Qt::StringLiterals;
30QgsExecuteSqlAlgorithm::QgsExecuteSqlAlgorithm()
44QString QgsExecuteSqlAlgorithm::name()
const
46 return u
"executesql"_s;
49QString QgsExecuteSqlAlgorithm::displayName()
const
51 return QObject::tr(
"Execute SQL" );
54QStringList QgsExecuteSqlAlgorithm::tags()
const
56 return QObject::tr(
"virtual,query,sql" ).split(
',' );
59QString QgsExecuteSqlAlgorithm::group()
const
61 return QObject::tr(
"Vector general" );
64QString QgsExecuteSqlAlgorithm::groupId()
const
66 return u
"vectorgeneral"_s;
69QString QgsExecuteSqlAlgorithm::shortDescription()
const
71 return QObject::tr(
"Runs an SQL query on vector layers using virtual layers." );
74QString QgsExecuteSqlAlgorithm::shortHelpString()
const
77 "This algorithm executes an SQL query on input vector layers using QGIS virtual layers.\n\n"
78 "Input layers are made available inside the query using aliases 'input1', 'input2', ..., 'inputN', corresponding to the order of layers supplied.\n\n"
79 "The query engine uses SQLite and SpatiaLite syntax, allowing spatial functions like ST_Intersects, ST_Buffer, and attribute aggregation. "
80 "Additionally, QGIS variable expressions in the format [% @var %] will be evaluated before running the query.\n\n"
81 "The result of the query will be materialized and stored in a new layer."
85QgsExecuteSqlAlgorithm *QgsExecuteSqlAlgorithm::createInstance()
const
87 return new QgsExecuteSqlAlgorithm();
95void QgsExecuteSqlAlgorithm::initAlgorithm(
const QVariantMap & )
97 auto inputDataSources = std::make_unique<
100 QObject::tr(
"Input vector layers to query. Inside the SQL statement, these layers are referenced as 'input1', 'input2', ..., 'inputN' according to their order in this list." )
102 addParameter( inputDataSources.release() );
104 auto inputQuery = std::make_unique<QgsProcessingParameterString>( u
"INPUT_QUERY"_s, QObject::tr(
"SQL query" ) );
106 QObject::tr(
"The SQL query to execute using SQLite/SpatiaLite syntax. Example: 'SELECT * FROM input1 WHERE area > 100'. Expressions enclosed in [% %] will be expanded before execution." )
108 inputQuery->setMetadata( { { u
"widget_wrapper"_s, QVariantMap( { { u
"widget_type"_s, u
"executesql"_s } } ) } } );
110 addParameter( inputQuery.release() );
112 auto inputUidField = std::make_unique<QgsProcessingParameterString>( u
"INPUT_UID_FIELD"_s, QObject::tr(
"Unique identifier field" ), QVariant(),
false,
true );
113 inputUidField->setHelp(
114 QObject::tr(
"Defines the field to be used as a unique integer identifier (primary key) for output features. If left empty, an autoincrementing ID field will be automatically generated." )
116 addParameter( inputUidField.release() );
118 auto inputGeometryField = std::make_unique<QgsProcessingParameterString>( u
"INPUT_GEOMETRY_FIELD"_s, QObject::tr(
"Geometry field" ), QVariant(),
false,
true );
119 inputGeometryField->setHelp( QObject::tr(
"Specifies the name of the column in the query output that contains the feature geometries (e.g. 'geometry' or 'geom')." ) );
120 addParameter( inputGeometryField.release() );
122 QStringList geometryTypeOptions;
123 geometryTypeOptions.reserve(
static_cast<int>( mGeometryTypes.size() ) );
124 for (
const std::pair<Qgis::WkbType, QString> &typePair : std::as_const( mGeometryTypes ) )
126 geometryTypeOptions.append( typePair.second );
129 auto inputGeometryType = std::make_unique<QgsProcessingParameterEnum>( u
"INPUT_GEOMETRY_TYPE"_s, QObject::tr(
"Geometry type" ), geometryTypeOptions,
false, 0 );
130 inputGeometryType->setHelp( QObject::tr(
"Explicitly defines the geometry type of the query result. If set to 'Autodetect', the algorithm will attempt to infer the type from the result features." ) );
131 addParameter( inputGeometryType.release() );
133 auto inputGeometryCrs = std::make_unique<QgsProcessingParameterCrs>( u
"INPUT_GEOMETRY_CRS"_s, QObject::tr(
"CRS" ), QVariant(),
true );
134 inputGeometryCrs->setHelp( QObject::tr(
"Specifies the coordinate reference system (CRS) for the output geometry. If left empty, the algorithm will attempt to infer the CRS from the input layers." ) );
135 addParameter( inputGeometryCrs.release() );
137 auto output = std::make_unique<QgsProcessingParameterFeatureSink>( u
"OUTPUT"_s, QObject::tr(
"SQL Output" ) );
138 output->setHelp( QObject::tr(
"Specifies the destination layer for the features returned by the SQL query." ) );
139 addParameter( output.release() );
144 const QList<QgsMapLayer *> layers = parameterAsLayerList( parameters, u
"INPUT_DATASOURCES"_s, context );
145 const QString query = parameterAsString( parameters, u
"INPUT_QUERY"_s, context );
146 const QString uniqueIdentifierField = parameterAsString( parameters, u
"INPUT_UID_FIELD"_s, context );
147 const QString geometryField = parameterAsString( parameters, u
"INPUT_GEOMETRY_FIELD"_s, context );
149 const int geometryTypeIndex = parameterAsEnum( parameters, u
"INPUT_GEOMETRY_TYPE"_s, context );
150 const Qgis::WkbType geometryType = ( geometryTypeIndex >= 0 && geometryTypeIndex < static_cast<int>( mGeometryTypes.size() ) ) ? mGeometryTypes.at( geometryTypeIndex ).first :
Qgis::WkbType::Unknown;
156 for (
QgsMapLayer *layer : std::as_const( layers ) )
158 QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
159 if ( !vectorLayer || !vectorLayer->
isValid() )
177 layerDefinition.
addSource( u
"input%1"_s.arg( layerIndex ), temporaryPath, u
"ogr"_s );
181 layerDefinition.
addSource( u
"input%1"_s.arg( layerIndex ), vectorLayer->
id() );
186 if ( query.trimmed().isEmpty() )
188 throw QgsProcessingException( QObject::tr(
"Empty SQL. Please enter valid SQL expression and try again." ) );
194 feedback->
pushInfo( QObject::tr(
"Executing query:" ) );
197 layerDefinition.
setQuery( expandedQuery );
199 if ( !uniqueIdentifierField.isEmpty() )
201 layerDefinition.
setUid( uniqueIdentifierField );
210 if ( !geometryField.isEmpty() )
225 if ( !virtualLayer.isValid() )
227 throw QgsProcessingException( virtualLayer.dataProvider() ? virtualLayer.dataProvider()->error().summary() : QObject::tr(
"Invalid virtual layer" ) );
235 QString destinationId;
236 std::unique_ptr<QgsFeatureSink> sink( parameterAsSink( parameters, u
"OUTPUT"_s, context, destinationId, virtualLayer.fields(), virtualLayer.wkbType(), virtualLayer.crs() ) );
243 const double progressStep = virtualLayer.featureCount() > 0 ? 100.0 / virtualLayer.featureCount() : 0.0;
244 long long currentFeatureIndex = 0;
246 while ( featureIterator.
nextFeature( inputFeature ) )
255 feedback->
setProgress(
static_cast<int>( currentFeatureIndex * progressStep ) );
256 currentFeatureIndex++;
262 outputs.insert( u
"OUTPUT"_s, destinationId );
@ Vector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
QFlags< ProcessingAlgorithmFlag > ProcessingAlgorithmFlags
Flags indicating how and when an algorithm operates and should be exposed to users.
WkbType
The WKB type describes the number of dimensions a geometry has.
@ MultiPolygon
MultiPolygon.
@ MultiLineString
MultiLineString.
@ NoThreading
Algorithm is not thread safe and cannot be run in a background thread, e.g. for algorithms which mani...
Represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
long postgisSrid() const
Returns PostGIS SRID for the CRS.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
static QString replaceExpressionText(const QString &action, const QgsExpressionContext *context, const QgsDistanceArea *distanceArea=nullptr)
This function replaces each expression between [% and %] in the string with the result of its evaluat...
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool isCanceled() const
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
Base class for all map layer types.
virtual Qgis::ProcessingAlgorithmFlags flags() const
Returns the flags indicating how and when the algorithm operates and should be exposed to users.
Contains information about the context in which a processing algorithm is executed.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
QgsProject * project() const
Returns the project in which the algorithm is being executed.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
void featureAddedToSink(const QString &output)
Reports that a feature was added to the the sink associated with the specified algorithm output.
virtual void pushCommandInfo(const QString &info)
Pushes an informational message containing a command from the algorithm.
virtual void pushInfo(const QString &info)
Pushes a general informational message from the algorithm.
void featureSinkFinalized(const QString &output)
Reports that a feature sink has been finalized.
void setHelp(const QString &help)
Sets the help for the parameter.
A parameter for processing algorithms which accepts multiple map layers.
static QString generateTempFilename(const QString &basename, const QgsProcessingContext *context=nullptr)
Returns a temporary filename for a given file, putting it into a temporary folder (creating that fold...
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
QString encoding() const
Returns the encoding which is used for accessing data.
Options to pass to QgsVectorFileWriter::writeAsVectorFormat().
QString fileEncoding
Encoding to use.
static QgsVectorFileWriter::WriterError writeAsVectorFormatV3(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *errorMessage=nullptr, QString *newFilename=nullptr, QString *newLayer=nullptr)
Writes a layer out to a vector file.
static QStringList supportedFormatExtensions(VectorFormatOptions options=SortRecommended)
Returns a list of file extensions for supported formats, e.g "shp", "gpkg".
Represents a vector layer which manages a vector based dataset.
QgsVectorDataProvider * dataProvider() final
Returns the layer's data provider, it may be nullptr.
Manipulates the definition of a virtual layer.
void setUid(const QString &uid)
Sets the name of the field with unique identifiers.
void setGeometrySrid(long srid)
Sets the SRID of the geometry.
void addSource(const QString &name, const QString &ref)
Add a live layer source layer.
void setGeometryField(const QString &geometryField)
Sets the name of the geometry field.
QString toString() const
Converts the definition into a QString that can be read by the virtual layer provider.
void setGeometryWkbType(Qgis::WkbType t)
Sets the type of the geometry.
void setQuery(const QString &query)
Sets the SQL query.