QGIS API Documentation 3.99.0-Master (357b655ed83)
Loading...
Searching...
No Matches
qgsalgorithmexporttopostgresql.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmexporttopostgresql.cpp
3 ---------------------
4 begin : November 2021
5 copyright : (C) 2021 by Clemens Raffler
6 email : clemens dot raffler 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"
23#include "qgsvectorfilewriter.h"
24
25#include <QString>
26
27using namespace Qt::StringLiterals;
28
30
31QString QgsExportToPostgresqlAlgorithm::name() const
32{
33 return u"importintopostgis"_s;
34}
35
36QString QgsExportToPostgresqlAlgorithm::displayName() const
37{
38 return u"Export to PostgreSQL"_s;
39}
40
41QStringList QgsExportToPostgresqlAlgorithm::tags() const
42{
43 return QObject::tr( "export,import,postgis,table,layer,into,copy" ).split( ',' );
44}
45
46QString QgsExportToPostgresqlAlgorithm::group() const
47{
48 return u"Database"_s;
49}
50
51QString QgsExportToPostgresqlAlgorithm::groupId() const
52{
53 return u"database"_s;
54}
55
56void QgsExportToPostgresqlAlgorithm::initAlgorithm( const QVariantMap & )
57{
58 addParameter( new QgsProcessingParameterFeatureSource( u"INPUT"_s, QObject::tr( "Layer to export" ), QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::Vector ) ) );
59 addParameter( new QgsProcessingParameterProviderConnection( u"DATABASE"_s, QObject::tr( "Database (connection name)" ), u"postgres"_s ) );
60 addParameter( new QgsProcessingParameterDatabaseSchema( u"SCHEMA"_s, QObject::tr( "Schema (schema name)" ), u"DATABASE"_s, u"public"_s, true ) );
61 addParameter( new QgsProcessingParameterDatabaseTable( u"TABLENAME"_s, QObject::tr( "Table to export to (leave blank to use layer name)" ), u"DATABASE"_s, u"SCHEMA"_s, QVariant(), true, true ) );
62 addParameter( new QgsProcessingParameterField( u"PRIMARY_KEY"_s, QObject::tr( "Primary key field" ), QVariant(), u"INPUT"_s, Qgis::ProcessingFieldParameterDataType::Any, false, true ) );
63 addParameter( new QgsProcessingParameterString( u"GEOMETRY_COLUMN"_s, QObject::tr( "Geometry column" ), u"geom"_s ) );
64 addParameter( new QgsProcessingParameterString( u"ENCODING"_s, QObject::tr( "Encoding" ), u"UTF-8"_s, false, true ) );
65 addParameter( new QgsProcessingParameterBoolean( u"OVERWRITE"_s, QObject::tr( "Overwrite" ), true ) );
66 addParameter( new QgsProcessingParameterBoolean( u"CREATEINDEX"_s, QObject::tr( "Create spatial index" ), true ) );
67 addParameter( new QgsProcessingParameterBoolean( u"LOWERCASE_NAMES"_s, QObject::tr( "Convert field names to lowercase" ), true ) );
68 addParameter( new QgsProcessingParameterBoolean( u"DROP_STRING_LENGTH"_s, QObject::tr( "Drop length constraints on character fields" ), false ) );
69 addParameter( new QgsProcessingParameterBoolean( u"FORCE_SINGLEPART"_s, QObject::tr( "Create single-part geometries instead of multipart" ), false ) );
70}
71
72QString QgsExportToPostgresqlAlgorithm::shortHelpString() const
73{
74 return QObject::tr( "This algorithm exports a vector layer to a PostgreSQL "
75 "database, creating a new table.\n\n"
76 "Prior to this a connection between QGIS and the PostgreSQL "
77 "database has to be created (for example through the QGIS Browser panel)."
78 );
79}
80
81QString QgsExportToPostgresqlAlgorithm::shortDescription() const
82{
83 return QObject::tr( "Exports a vector layer to a PostgreSQL database." );
84}
85
86QgsExportToPostgresqlAlgorithm *QgsExportToPostgresqlAlgorithm::createInstance() const
87{
88 return new QgsExportToPostgresqlAlgorithm();
89}
90
91bool QgsExportToPostgresqlAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
92{
93 mSource.reset( parameterAsSource( parameters, u"INPUT"_s, context ) );
94 if ( !mSource )
95 throw QgsProcessingException( invalidSourceError( parameters, u"INPUT"_s ) );
96
97 const QString connectionName = parameterAsConnectionName( parameters, u"DATABASE"_s, context );
98
99 try
100 {
102 mConn.reset( static_cast<QgsAbstractDatabaseProviderConnection *>( md->createConnection( connectionName ) ) );
103 }
105 {
106 QgsProcessingException( QObject::tr( "Could not retrieve connection details for %1" ).arg( connectionName ) );
107 }
108
109 mSchema = parameterAsSchema( parameters, u"SCHEMA"_s, context );
110 mPrimaryKeyField = parameterAsString( parameters, u"PRIMARY_KEY"_s, context );
111 mEncoding = parameterAsString( parameters, u"ENCODING"_s, context );
112 mOverwrite = parameterAsBoolean( parameters, u"OVERWRITE"_s, context );
113
114 mTable = parameterAsDatabaseTableName( parameters, u"TABLENAME"_s, context ).trimmed();
115 if ( mTable.isEmpty() )
116 {
117 mTable = mSource->sourceName();
118 mTable = mTable.replace( '.', '_' );
119 }
120 mTable = mTable.replace( ' ', QString() ).right( 63 );
121
122 mGeomColumn = parameterAsString( parameters, u"GEOMETRY_COLUMN"_s, context );
123 if ( mGeomColumn.isEmpty() )
124 mGeomColumn = u"geom"_s;
125 if ( mSource->wkbType() == Qgis::WkbType::NoGeometry )
126 mGeomColumn.clear();
127
128 mCreateIndex = parameterAsBoolean( parameters, u"CREATEINDEX"_s, context );
129
130 if ( mOverwrite )
131 mOptions[u"overwrite"_s] = true;
132 if ( parameterAsBoolean( parameters, u"LOWERCASE_NAMES"_s, context ) )
133 {
134 mOptions[u"lowercaseFieldNames"_s] = true;
135 mGeomColumn = mGeomColumn.toLower();
136 }
137 if ( parameterAsBoolean( parameters, u"DROP_STRING_LENGTH"_s, context ) )
138 mOptions[u"dropStringConstraints"_s] = true;
139 if ( parameterAsBoolean( parameters, u"FORCE_SINGLEPART"_s, context ) )
140 mOptions[u"forceSinglePartGeometryType"_s] = true;
141 if ( !mEncoding.isEmpty() )
142 mOptions[u"fileEncoding"_s] = mEncoding;
143
144 return true;
145}
146
147QVariantMap QgsExportToPostgresqlAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
148{
149 Q_UNUSED( parameters );
150 Q_UNUSED( context );
151
152 QgsDataSourceUri uri = QgsDataSourceUri( mConn->uri() );
153 uri.setSchema( mSchema );
154 uri.setTable( mTable );
155 uri.setKeyColumn( mPrimaryKeyField );
156 uri.setGeometryColumn( mGeomColumn );
157
158 auto exporter = std::make_unique<QgsVectorLayerExporter>( uri.uri(), mProviderName, mSource->fields(), mSource->wkbType(), mSource->sourceCrs(), mOverwrite, mOptions );
159
160 if ( exporter->errorCode() != Qgis::VectorExportResult::Success )
161 throw QgsProcessingException( QObject::tr( "Error exporting to PostGIS\n%1" ).arg( exporter->errorMessage() ) );
162
163 QgsFeatureIterator featureIterator = mSource->getFeatures();
164
165 const double progressStep = ( mSource->featureCount() ) ? 100.0 / mSource->featureCount() : 0.0;
166
167 qgssize i = 0;
168 QgsFeature f;
169 while ( featureIterator.nextFeature( f ) )
170 {
171 if ( feedback->isCanceled() )
172 break;
173
174 if ( !exporter->addFeature( f, QgsFeatureSink::FastInsert ) )
175 feedback->reportError( exporter->errorMessage() );
176
177 feedback->setProgress( i * progressStep );
178 i++;
179 }
180 exporter->flushBuffer();
181
182 if ( exporter->errorCode() != Qgis::VectorExportResult::Success )
183 throw QgsProcessingException( QObject::tr( "Error exporting to PostGIS\n%1" ).arg( exporter->errorMessage() ) );
184
185 exporter.reset();
186
187 if ( !mGeomColumn.isEmpty() && mCreateIndex )
188 {
189 try
190 {
192 opt.geometryColumnName = mGeomColumn;
193 mConn->createSpatialIndex( mSchema, mTable, opt );
194 }
196 {
197 throw QgsProcessingException( QObject::tr( "Error creating spatial index:\n%1" ).arg( ex.what() ) );
198 }
199 }
200
201 try
202 {
203 mConn->vacuum( mSchema, mTable );
204 }
206 {
207 feedback->reportError( QObject::tr( "Error vacuuming table:\n{0}" ).arg( ex.what() ) );
208 }
209
210 QVariantMap outputs;
211 return outputs;
212}
@ 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.
Stores the component parts of a data source URI (e.g.
void setSchema(const QString &schema)
Sets the scheme for the URI.
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: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
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 schema parameter for processing algorithms, allowing users to select from existing schemas...
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.
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...
Definition qgis.h:7458
The SpatialIndexOptions contains extra options relating to spatial index creation.
QString geometryColumnName
Specifies the name of the geometry column to create the index for.