QGIS API Documentation 4.3.0-Master (ffcfc20b9b4)
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 QGS_MARK_ALGORITHM_SOURCE
98
99 std::unique_ptr<QgsProcessingFeatureSource> source( parameterAsSource( parameters, u"INPUT"_s, context ) );
100 if ( !source )
101 throw QgsProcessingException( invalidSourceError( parameters, u"INPUT"_s ) );
102
103 QgsDataSourceUri uri( mDatabaseUri );
104 if ( uri.database().isEmpty() )
105 {
107 const QVariantMap parts = md->decodeUri( mDatabaseUri );
108 mDatabaseUri = parts.value( u"path"_s ).toString();
109 uri = QgsDataSourceUri( u"dbname='%1'"_s.arg( mDatabaseUri ) );
110 }
111
112 std::unique_ptr<QgsAbstractDatabaseProviderConnection> conn;
113 try
114 {
116 conn.reset( static_cast<QgsAbstractDatabaseProviderConnection *>( md->createConnection( uri.uri(), QVariantMap() ) ) );
117 }
119 {
120 throw QgsProcessingException( QObject::tr( "Could not connect to %1" ).arg( uri.uri() ) );
121 }
122
123 const QString primaryKeyField = parameterAsString( parameters, u"PRIMARY_KEY"_s, context );
124 const QString encoding = parameterAsString( parameters, u"ENCODING"_s, context );
125 const bool overwrite = parameterAsBoolean( parameters, u"OVERWRITE"_s, context );
126
127 QString tableName = parameterAsDatabaseTableName( parameters, u"TABLENAME"_s, context ).trimmed();
128 if ( tableName.isEmpty() )
129 {
130 tableName = source->sourceName();
131 tableName = tableName.replace( '.', '_' );
132 }
133 tableName = tableName.replace( ' ', QString() ).right( 63 );
134
135 QString geometryColumn = parameterAsString( parameters, u"GEOMETRY_COLUMN"_s, context );
136 if ( geometryColumn.isEmpty() )
137 {
138 geometryColumn = u"geom"_s;
139 }
140 if ( source->wkbType() == Qgis::WkbType::NoGeometry )
141 {
142 geometryColumn.clear();
143 }
144
145 const bool createSpatialIndex = parameterAsBoolean( parameters, u"CREATEINDEX"_s, context );
146
147 QMap<QString, QVariant> options;
148 if ( overwrite )
149 {
150 options[u"overwrite"_s] = true;
151 }
152 if ( parameterAsBoolean( parameters, u"LOWERCASE_NAMES"_s, context ) )
153 {
154 options[u"lowercaseFieldNames"_s] = true;
155 geometryColumn = geometryColumn.toLower();
156 }
157 if ( parameterAsBoolean( parameters, u"DROP_STRING_LENGTH"_s, context ) )
158 {
159 options[u"dropStringConstraints"_s] = true;
160 }
161 if ( parameterAsBoolean( parameters, u"FORCE_SINGLEPART"_s, context ) )
162 {
163 options[u"forceSinglePartGeometryType"_s] = true;
164 }
165 if ( !encoding.isEmpty() )
166 {
167 options[u"fileEncoding"_s] = encoding;
168 }
169
170 uri = QgsDataSourceUri( conn->uri() );
171 uri.setTable( tableName );
172 uri.setKeyColumn( primaryKeyField );
173 uri.setGeometryColumn( geometryColumn );
174
175 auto exporter = std::make_unique<QgsVectorLayerExporter>( uri.uri(), u"spatialite"_s, source->fields(), source->wkbType(), source->sourceCrs(), overwrite, options );
176
177 if ( exporter->errorCode() != Qgis::VectorExportResult::Success )
178 throw QgsProcessingException( QObject::tr( "Error exporting to SpatiaLite\n%1" ).arg( exporter->errorMessage() ) );
179
180 QgsFeatureIterator featureIterator = source->getFeatures();
181
182 const double step = source->featureCount() > 0 ? 100.0 / source->featureCount() : 0.0;
183
184 long long i = 0;
185 QgsFeature f;
186 while ( featureIterator.nextFeature( f ) )
187 {
188 if ( feedback->isCanceled() )
189 {
190 break;
191 }
192
193 if ( !exporter->addFeature( f, QgsFeatureSink::FastInsert ) )
194 {
195 feedback->reportError( exporter->errorMessage() );
196 }
197
198 feedback->setProgress( i * step );
199 i++;
200 }
201 exporter->flushBuffer();
202
203 if ( exporter->errorCode() != Qgis::VectorExportResult::Success )
204 throw QgsProcessingException( QObject::tr( "Error exporting to SpatiaLite\n%1" ).arg( exporter->errorMessage() ) );
205
206 exporter.reset();
207
208 if ( !geometryColumn.isEmpty() && createSpatialIndex )
209 {
210 try
211 {
213 opt.geometryColumnName = geometryColumn;
214 conn->createSpatialIndex( "", tableName, opt );
215 }
217 {
218 throw QgsProcessingException( QObject::tr( "Error creating spatial index:\n%1" ).arg( e.what() ) );
219 }
220 }
221
222 try
223 {
224 conn->vacuum( "", tableName );
225 }
227 {
228 feedback->reportError( QObject::tr( "Error vacuuming table:\n%1" ).arg( e.what() ) );
229 }
230
231 QVariantMap outputs;
232 return outputs;
233}
234
@ Vector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
Definition qgis.h:3755
@ Success
No errors were encountered.
Definition qgis.h:1134
@ NoGeometry
No geometry.
Definition qgis.h:312
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:56
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition qgsfeedback.h:65
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.