QGIS API Documentation 3.99.0-Master (357b655ed83)
Loading...
Searching...
No Matches
qgsalgorithmexporttospatialite.cpp
Go to the documentation of this file.
1
2/***************************************************************************
3 qgsalgorithmexporttospatialite.cpp
4 ---------------------
5 begin : April 2025
6 copyright : (C) 2025 by Alexander Bruy
7 email : alexander dot bruy at gmail dot com
8 ***************************************************************************/
9
10/***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
18
20
22#include "qgsprovidermetadata.h"
23#include "qgsproviderregistry.h"
25
26#include <QString>
27
28using namespace Qt::StringLiterals;
29
31
32QString QgsExportToSpatialiteAlgorithm::name() const
33{
34 return u"importintospatialite"_s;
35}
36
37QString QgsExportToSpatialiteAlgorithm::displayName() const
38{
39 return QObject::tr( "Export to SpatiaLite" );
40}
41
42QStringList QgsExportToSpatialiteAlgorithm::tags() const
43{
44 return QObject::tr( "export,import,spatialite,table,layer,into,copy" ).split( ',' );
45}
46
47QString QgsExportToSpatialiteAlgorithm::group() const
48{
49 return QObject::tr( "Database" );
50}
51
52QString QgsExportToSpatialiteAlgorithm::groupId() const
53{
54 return u"database"_s;
55}
56
57QString QgsExportToSpatialiteAlgorithm::shortHelpString() const
58{
59 return QObject::tr( "This algorithm exports a vector layer to a SpatiaLite database, creating a new table." );
60}
61
62QString QgsExportToSpatialiteAlgorithm::shortDescription() const
63{
64 return QObject::tr( "Exports a vector layer to a SpatiaLite database, creating a new table." );
65}
66
67QgsExportToSpatialiteAlgorithm *QgsExportToSpatialiteAlgorithm::createInstance() const
68{
69 return new QgsExportToSpatialiteAlgorithm();
70}
71
72void QgsExportToSpatialiteAlgorithm::initAlgorithm( const QVariantMap & )
73{
74 addParameter( new QgsProcessingParameterFeatureSource( u"INPUT"_s, QObject::tr( "Layer to export" ), QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::Vector ) ) );
75 addParameter( new QgsProcessingParameterVectorLayer( u"DATABASE"_s, QObject::tr( "Database layer (or file)" ), QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::Vector ) ) );
76 addParameter( new QgsProcessingParameterString( u"TABLENAME"_s, QObject::tr( "Table to export to (leave blank to use layer name)" ), QVariant(), false, true ) );
77 addParameter( new QgsProcessingParameterField( u"PRIMARY_KEY"_s, QObject::tr( "Primary key field" ), QVariant(), u"INPUT"_s, Qgis::ProcessingFieldParameterDataType::Any, false, true ) );
78 addParameter( new QgsProcessingParameterString( u"GEOMETRY_COLUMN"_s, QObject::tr( "Geometry column" ), u"geom"_s ) );
79 addParameter( new QgsProcessingParameterString( u"ENCODING"_s, QObject::tr( "Encoding" ), u"UTF-8"_s, false, true ) );
80 addParameter( new QgsProcessingParameterBoolean( u"OVERWRITE"_s, QObject::tr( "Overwrite" ), true ) );
81 addParameter( new QgsProcessingParameterBoolean( u"CREATEINDEX"_s, QObject::tr( "Create spatial index" ), true ) );
82 addParameter( new QgsProcessingParameterBoolean( u"LOWERCASE_NAMES"_s, QObject::tr( "Convert field names to lowercase" ), true ) );
83 addParameter( new QgsProcessingParameterBoolean( u"DROP_STRING_LENGTH"_s, QObject::tr( "Drop length constraints on character fields" ), false ) );
84 addParameter( new QgsProcessingParameterBoolean( u"FORCE_SINGLEPART"_s, QObject::tr( "Create single-part geometries instead of multipart" ), false ) );
85}
86
87bool QgsExportToSpatialiteAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
88{
89 QgsVectorLayer *layer = parameterAsVectorLayer( parameters, u"DATABASE"_s, context );
90 mProviderType = layer->providerType();
91 mDatabaseUri = layer->dataProvider()->dataSourceUri();
92 return true;
93}
94
95QVariantMap QgsExportToSpatialiteAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
96{
97 std::unique_ptr<QgsProcessingFeatureSource> source( parameterAsSource( parameters, u"INPUT"_s, context ) );
98 if ( !source )
99 throw QgsProcessingException( invalidSourceError( parameters, u"INPUT"_s ) );
100
101 QgsDataSourceUri uri( mDatabaseUri );
102 if ( uri.database().isEmpty() )
103 {
105 const QVariantMap parts = md->decodeUri( mDatabaseUri );
106 mDatabaseUri = parts.value( u"path"_s ).toString();
107 uri = QgsDataSourceUri( u"dbname='%1'"_s.arg( mDatabaseUri ) );
108 }
109
110 std::unique_ptr<QgsAbstractDatabaseProviderConnection> conn;
111 try
112 {
114 conn.reset( static_cast<QgsAbstractDatabaseProviderConnection *>( md->createConnection( uri.uri(), QVariantMap() ) ) );
115 }
117 {
118 throw QgsProcessingException( QObject::tr( "Could not connect to %1" ).arg( uri.uri() ) );
119 }
120
121 const QString primaryKeyField = parameterAsString( parameters, u"PRIMARY_KEY"_s, context );
122 const QString encoding = parameterAsString( parameters, u"ENCODING"_s, context );
123 const bool overwrite = parameterAsBoolean( parameters, u"OVERWRITE"_s, context );
124
125 QString tableName = parameterAsDatabaseTableName( parameters, u"TABLENAME"_s, context ).trimmed();
126 if ( tableName.isEmpty() )
127 {
128 tableName = source->sourceName();
129 tableName = tableName.replace( '.', '_' );
130 }
131 tableName = tableName.replace( ' ', QString() ).right( 63 );
132
133 QString geometryColumn = parameterAsString( parameters, u"GEOMETRY_COLUMN"_s, context );
134 if ( geometryColumn.isEmpty() )
135 {
136 geometryColumn = u"geom"_s;
137 }
138 if ( source->wkbType() == Qgis::WkbType::NoGeometry )
139 {
140 geometryColumn.clear();
141 }
142
143 const bool createSpatialIndex = parameterAsBoolean( parameters, u"CREATEINDEX"_s, context );
144
145 QMap<QString, QVariant> options;
146 if ( overwrite )
147 {
148 options[u"overwrite"_s] = true;
149 }
150 if ( parameterAsBoolean( parameters, u"LOWERCASE_NAMES"_s, context ) )
151 {
152 options[u"lowercaseFieldNames"_s] = true;
153 geometryColumn = geometryColumn.toLower();
154 }
155 if ( parameterAsBoolean( parameters, u"DROP_STRING_LENGTH"_s, context ) )
156 {
157 options[u"dropStringConstraints"_s] = true;
158 }
159 if ( parameterAsBoolean( parameters, u"FORCE_SINGLEPART"_s, context ) )
160 {
161 options[u"forceSinglePartGeometryType"_s] = true;
162 }
163 if ( !encoding.isEmpty() )
164 {
165 options[u"fileEncoding"_s] = encoding;
166 }
167
168 uri = QgsDataSourceUri( conn->uri() );
169 uri.setTable( tableName );
170 uri.setKeyColumn( primaryKeyField );
171 uri.setGeometryColumn( geometryColumn );
172
173 auto exporter = std::make_unique<QgsVectorLayerExporter>( uri.uri(), u"spatialite"_s, source->fields(), source->wkbType(), source->sourceCrs(), overwrite, options );
174
175 if ( exporter->errorCode() != Qgis::VectorExportResult::Success )
176 throw QgsProcessingException( QObject::tr( "Error exporting to SpatiaLite\n%1" ).arg( exporter->errorMessage() ) );
177
178 QgsFeatureIterator featureIterator = source->getFeatures();
179
180 const double step = source->featureCount() > 0 ? 100.0 / source->featureCount() : 0.0;
181
182 long long i = 0;
183 QgsFeature f;
184 while ( featureIterator.nextFeature( f ) )
185 {
186 if ( feedback->isCanceled() )
187 {
188 break;
189 }
190
191 if ( !exporter->addFeature( f, QgsFeatureSink::FastInsert ) )
192 {
193 feedback->reportError( exporter->errorMessage() );
194 }
195
196 feedback->setProgress( i * step );
197 i++;
198 }
199 exporter->flushBuffer();
200
201 if ( exporter->errorCode() != Qgis::VectorExportResult::Success )
202 throw QgsProcessingException( QObject::tr( "Error exporting to SpatiaLite\n%1" ).arg( exporter->errorMessage() ) );
203
204 exporter.reset();
205
206 if ( !geometryColumn.isEmpty() && createSpatialIndex )
207 {
208 try
209 {
211 opt.geometryColumnName = geometryColumn;
212 conn->createSpatialIndex( "", tableName, opt );
213 }
215 {
216 throw QgsProcessingException( QObject::tr( "Error creating spatial index:\n%1" ).arg( e.what() ) );
217 }
218 }
219
220 try
221 {
222 conn->vacuum( "", tableName );
223 }
225 {
226 feedback->reportError( QObject::tr( "Error vacuuming table:\n%1" ).arg( e.what() ) );
227 }
228
229 QVariantMap outputs;
230 return outputs;
231}
232
@ Vector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
Definition qgis.h:3610
@ Success
No errors were encountered.
Definition qgis.h:1072
@ NoGeometry
No geometry.
Definition qgis.h:298
Provides common functionality for database based connections.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
Stores the component parts of a data source URI (e.g.
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:60
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:55
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition qgsfeedback.h:63
QString providerType() const
Returns the provider type (provider key) for this layer.
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.
An input feature source (such as vector layers) parameter for processing algorithms.
A vector layer or feature source field parameter for processing algorithms.
A string parameter for processing algorithms.
A vector layer (with or without geometry) 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...
virtual QVariantMap decodeUri(const QString &uri) const
Breaks a provider data source URI into its component paths (e.g.
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.
Represents a vector layer which manages a vector based dataset.
QgsVectorDataProvider * dataProvider() final
Returns the layer's data provider, it may be nullptr.
The SpatialIndexOptions contains extra options relating to spatial index creation.
QString geometryColumnName
Specifies the name of the geometry column to create the index for.