QGIS API Documentation 3.99.0-Master (21b3aa880ba)
Loading...
Searching...
No Matches
qgsalgorithmexporttospatialiteregistered.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmexporttospatialiteregistered.cpp
3 ---------------------
4 begin : April 2025
5 copyright : (C) 2025 by Alexander Bruy
6 email : alexander dot bruy at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19
21#include "qgsprovidermetadata.h"
22#include "qgsproviderregistry.h"
24
26
27QString QgsExportToRegisteredSpatialiteAlgorithm::name() const
28{
29 return QStringLiteral( "importintospatialiteregistered" );
30}
31
32QString QgsExportToRegisteredSpatialiteAlgorithm::displayName() const
33{
34 return QObject::tr( "Export to SpatiaLite (registered)" );
35}
36
37QStringList QgsExportToRegisteredSpatialiteAlgorithm::tags() const
38{
39 return QObject::tr( "export,import,spatialite,table,layer,into,copy" ).split( ',' );
40}
41
42QString QgsExportToRegisteredSpatialiteAlgorithm::group() const
43{
44 return QObject::tr( "Database" );
45}
46
47QString QgsExportToRegisteredSpatialiteAlgorithm::groupId() const
48{
49 return QStringLiteral( "database" );
50}
51
52QString QgsExportToRegisteredSpatialiteAlgorithm::shortHelpString() const
53{
54 return QObject::tr( "Exports a vector layer to a SpatiaLite database, creating "
55 "a new table.\n\n"
56 "Prior to this a connection between QGIS and the SpatiaLite "
57 "database has to be created (for example through the QGIS "
58 "Browser panel)." );
59}
60
61QString QgsExportToRegisteredSpatialiteAlgorithm::shortDescription() const
62{
63 return QObject::tr( "Exports a vector layer to a registered SpatiaLite database, creating a new table." );
64}
65
66Qgis::ProcessingAlgorithmFlags QgsExportToRegisteredSpatialiteAlgorithm::flags() const
67{
69}
70
71QgsExportToRegisteredSpatialiteAlgorithm *QgsExportToRegisteredSpatialiteAlgorithm::createInstance() const
72{
73 return new QgsExportToRegisteredSpatialiteAlgorithm();
74}
75
76void QgsExportToRegisteredSpatialiteAlgorithm::initAlgorithm( const QVariantMap & )
77{
78 addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Layer to export" ), QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::Vector ) ) );
79 addParameter( new QgsProcessingParameterProviderConnection( QStringLiteral( "DATABASE" ), QObject::tr( "Database (connection name)" ), QStringLiteral( "spatialite" ) ) );
80 addParameter( new QgsProcessingParameterDatabaseTable( QStringLiteral( "TABLENAME" ), QObject::tr( "Table to export to (leave blank to use layer name)" ), QStringLiteral( "DATABASE" ), QString(), QVariant(), true, true ) );
81 addParameter( new QgsProcessingParameterField( QStringLiteral( "PRIMARY_KEY" ), QObject::tr( "Primary key field" ), QVariant(), QStringLiteral( "INPUT" ), Qgis::ProcessingFieldParameterDataType::Any, false, true ) );
82 addParameter( new QgsProcessingParameterString( QStringLiteral( "GEOMETRY_COLUMN" ), QObject::tr( "Geometry column" ), QStringLiteral( "geom" ) ) );
83 addParameter( new QgsProcessingParameterString( QStringLiteral( "ENCODING" ), QObject::tr( "Encoding" ), QStringLiteral( "UTF-8" ), false, true ) );
84 addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "OVERWRITE" ), QObject::tr( "Overwrite" ), true ) );
85 addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "CREATEINDEX" ), QObject::tr( "Create spatial index" ), true ) );
86 addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "LOWERCASE_NAMES" ), QObject::tr( "Convert field names to lowercase" ), true ) );
87 addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "DROP_STRING_LENGTH" ), QObject::tr( "Drop length constraints on character fields" ), false ) );
88 addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "FORCE_SINGLEPART" ), QObject::tr( "Create single-part geometries instead of multipart" ), false ) );
89}
90
91QVariantMap QgsExportToRegisteredSpatialiteAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
92{
93 std::unique_ptr<QgsProcessingFeatureSource> source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
94 if ( !source )
95 throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
96
97 const QString connectionName = parameterAsConnectionName( parameters, QStringLiteral( "DATABASE" ), context );
98
99 std::unique_ptr<QgsAbstractDatabaseProviderConnection> conn;
100 try
101 {
102 QgsProviderMetadata *md = QgsProviderRegistry::instance()->providerMetadata( QStringLiteral( "spatialite" ) );
103 conn.reset( static_cast<QgsAbstractDatabaseProviderConnection *>( md->createConnection( connectionName ) ) );
104 }
106 {
107 QgsProcessingException( QObject::tr( "Could not retrieve connection details for %1" ).arg( connectionName ) );
108 }
109
110 const QString primaryKeyField = parameterAsString( parameters, QStringLiteral( "PRIMARY_KEY" ), context );
111 const QString encoding = parameterAsString( parameters, QStringLiteral( "ENCODING" ), context );
112 const bool overwrite = parameterAsBoolean( parameters, QStringLiteral( "OVERWRITE" ), context );
113
114 QString tableName = parameterAsDatabaseTableName( parameters, QStringLiteral( "TABLENAME" ), context ).trimmed();
115 if ( tableName.isEmpty() )
116 {
117 tableName = source->sourceName();
118 tableName = tableName.replace( '.', '_' );
119 }
120 tableName = tableName.replace( ' ', QString() ).right( 63 );
121
122 QString geometryColumn = parameterAsString( parameters, QStringLiteral( "GEOMETRY_COLUMN" ), context );
123 if ( geometryColumn.isEmpty() )
124 {
125 geometryColumn = QStringLiteral( "geom" );
126 }
127 if ( source->wkbType() == Qgis::WkbType::NoGeometry )
128 {
129 geometryColumn.clear();
130 }
131
132 const bool createSpatialIndex = parameterAsBoolean( parameters, QStringLiteral( "CREATEINDEX" ), context );
133
134 QMap<QString, QVariant> options;
135 if ( overwrite )
136 {
137 options[QStringLiteral( "overwrite" )] = true;
138 }
139 if ( parameterAsBoolean( parameters, QStringLiteral( "LOWERCASE_NAMES" ), context ) )
140 {
141 options[QStringLiteral( "lowercaseFieldNames" )] = true;
142 geometryColumn = geometryColumn.toLower();
143 }
144 if ( parameterAsBoolean( parameters, QStringLiteral( "DROP_STRING_LENGTH" ), context ) )
145 {
146 options[QStringLiteral( "dropStringConstraints" )] = true;
147 }
148 if ( parameterAsBoolean( parameters, QStringLiteral( "FORCE_SINGLEPART" ), context ) )
149 {
150 options[QStringLiteral( "forceSinglePartGeometryType" )] = true;
151 }
152 if ( !encoding.isEmpty() )
153 {
154 options[QStringLiteral( "fileEncoding" )] = encoding;
155 }
156
157 QgsDataSourceUri uri = QgsDataSourceUri( conn->uri() );
158 uri.setTable( tableName );
159 uri.setKeyColumn( primaryKeyField );
160 uri.setGeometryColumn( geometryColumn );
161
162 auto exporter = std::make_unique<QgsVectorLayerExporter>( uri.uri(), QStringLiteral( "spatialite" ), source->fields(), source->wkbType(), source->sourceCrs(), overwrite, options );
163
164 if ( exporter->errorCode() != Qgis::VectorExportResult::Success )
165 throw QgsProcessingException( QObject::tr( "Error exporting to SpatiaLite\n%1" ).arg( exporter->errorMessage() ) );
166
167 QgsFeatureIterator featureIterator = source->getFeatures();
168
169 const double step = source->featureCount() > 0 ? 100.0 / source->featureCount() : 0.0;
170
171 long long i = 0;
172 QgsFeature f;
173 while ( featureIterator.nextFeature( f ) )
174 {
175 if ( feedback->isCanceled() )
176 {
177 break;
178 }
179
180 if ( !exporter->addFeature( f, QgsFeatureSink::FastInsert ) )
181 {
182 feedback->reportError( exporter->errorMessage() );
183 }
184
185 feedback->setProgress( i * step );
186 i++;
187 }
188 exporter->flushBuffer();
189
190 if ( exporter->errorCode() != Qgis::VectorExportResult::Success )
191 throw QgsProcessingException( QObject::tr( "Error exporting to SpatiaLite\n%1" ).arg( exporter->errorMessage() ) );
192
193 exporter.reset();
194
195 if ( !geometryColumn.isEmpty() && createSpatialIndex )
196 {
197 try
198 {
200 opt.geometryColumnName = geometryColumn;
201 conn->createSpatialIndex( "", tableName, opt );
202 }
204 {
205 throw QgsProcessingException( QObject::tr( "Error creating spatial index:\n%1" ).arg( e.what() ) );
206 }
207 }
208
209 try
210 {
211 conn->vacuum( "", tableName );
212 }
214 {
215 feedback->reportError( QObject::tr( "Error vacuuming table:\n%1" ).arg( e.what() ) );
216 }
217
218 QVariantMap outputs;
219 return outputs;
220}
221
@ Vector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
Definition qgis.h:3539
@ Success
No errors were encountered.
Definition qgis.h:1053
QFlags< ProcessingAlgorithmFlag > ProcessingAlgorithmFlags
Flags indicating how and when an algorithm operates and should be exposed to users.
Definition qgis.h:3609
@ NoGeometry
No geometry.
Definition qgis.h:294
@ NoThreading
Algorithm is not thread safe and cannot be run in a background thread, e.g. for algorithms which mani...
Definition qgis.h:3588
Provides common functionality for database based connections.
Stores the component parts of a data source URI (e.g.
void setTable(const QString &table)
Sets table to table.
void setGeometryColumn(const QString &geometryColumn)
Sets geometry column name to geometryColumn.
QString uri(bool expandAuthConfig=true) const
Returns the complete URI as a string.
void setKeyColumn(const QString &column)
Sets the name of the (primary) key column.
QString what() const
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...
Definition qgsfeature.h:58
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:53
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition qgsfeedback.h:61
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.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
A boolean parameter for processing algorithms.
A database table name parameter for processing algorithms.
An input feature source (such as vector layers) parameter for processing algorithms.
A vector layer or feature source field parameter for processing algorithms.
A data provider connection parameter for processing algorithms, allowing users to select from availab...
A string parameter for processing algorithms.
Custom exception class for provider connection related exceptions.
Holds data provider key, description, and associated shared library file or function pointer informat...
virtual QgsAbstractProviderConnection * createConnection(const QString &uri, const QVariantMap &configuration)
Creates a new connection from uri and configuration, the newly created connection is not automaticall...
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QgsProviderMetadata * providerMetadata(const QString &providerKey) const
Returns metadata of the provider or nullptr if not found.
The SpatialIndexOptions contains extra options relating to spatial index creation.
QString geometryColumnName
Specifies the name of the geometry column to create the index for.