QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
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(
75 "This algorithm exports a vector layer to a PostgreSQL "
76 "database, creating a new table.\n\n"
77 "Prior to this a connection between QGIS and the PostgreSQL "
78 "database has to be created (for example through the QGIS Browser panel)."
79 );
80}
81
82QString QgsExportToPostgresqlAlgorithm::shortDescription() const
83{
84 return QObject::tr( "Exports a vector layer to a PostgreSQL database." );
85}
86
87QgsExportToPostgresqlAlgorithm *QgsExportToPostgresqlAlgorithm::createInstance() const
88{
89 return new QgsExportToPostgresqlAlgorithm();
90}
91
92bool QgsExportToPostgresqlAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
93{
94 mSource.reset( parameterAsSource( parameters, u"INPUT"_s, context ) );
95 if ( !mSource )
96 throw QgsProcessingException( invalidSourceError( parameters, u"INPUT"_s ) );
97
98 const QString connectionName = parameterAsConnectionName( parameters, u"DATABASE"_s, context );
99
100 try
101 {
103 mConn.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 mSchema = parameterAsSchema( parameters, u"SCHEMA"_s, context );
111 mPrimaryKeyField = parameterAsString( parameters, u"PRIMARY_KEY"_s, context );
112 mEncoding = parameterAsString( parameters, u"ENCODING"_s, context );
113 mOverwrite = parameterAsBoolean( parameters, u"OVERWRITE"_s, context );
114
115 mTable = parameterAsDatabaseTableName( parameters, u"TABLENAME"_s, context ).trimmed();
116 if ( mTable.isEmpty() )
117 {
118 mTable = mSource->sourceName();
119 mTable = mTable.replace( '.', '_' );
120 }
121 mTable = mTable.replace( ' ', QString() ).right( 63 );
122
123 mGeomColumn = parameterAsString( parameters, u"GEOMETRY_COLUMN"_s, context );
124 if ( mGeomColumn.isEmpty() )
125 mGeomColumn = u"geom"_s;
126 if ( mSource->wkbType() == Qgis::WkbType::NoGeometry )
127 mGeomColumn.clear();
128
129 mCreateIndex = parameterAsBoolean( parameters, u"CREATEINDEX"_s, context );
130
131 if ( mOverwrite )
132 mOptions[u"overwrite"_s] = true;
133 if ( parameterAsBoolean( parameters, u"LOWERCASE_NAMES"_s, context ) )
134 {
135 mOptions[u"lowercaseFieldNames"_s] = true;
136 mGeomColumn = mGeomColumn.toLower();
137 }
138 if ( parameterAsBoolean( parameters, u"DROP_STRING_LENGTH"_s, context ) )
139 mOptions[u"dropStringConstraints"_s] = true;
140 if ( parameterAsBoolean( parameters, u"FORCE_SINGLEPART"_s, context ) )
141 mOptions[u"forceSinglePartGeometryType"_s] = true;
142 if ( !mEncoding.isEmpty() )
143 mOptions[u"fileEncoding"_s] = mEncoding;
144
145 return true;
146}
147
148QVariantMap QgsExportToPostgresqlAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
149{
150 Q_UNUSED( parameters );
151 Q_UNUSED( context );
152
153 QgsDataSourceUri uri = QgsDataSourceUri( mConn->uri() );
154 uri.setSchema( mSchema );
155 uri.setTable( mTable );
156 uri.setKeyColumn( mPrimaryKeyField );
157 uri.setGeometryColumn( mGeomColumn );
158
159 auto exporter = std::make_unique<QgsVectorLayerExporter>( uri.uri(), mProviderName, mSource->fields(), mSource->wkbType(), mSource->sourceCrs(), mOverwrite, mOptions );
160
161 if ( exporter->errorCode() != Qgis::VectorExportResult::Success )
162 throw QgsProcessingException( QObject::tr( "Error exporting to PostGIS\n%1" ).arg( exporter->errorMessage() ) );
163
164 QgsFeatureIterator featureIterator = mSource->getFeatures();
165
166 const double progressStep = ( mSource->featureCount() ) ? 100.0 / mSource->featureCount() : 0.0;
167
168 qgssize i = 0;
169 QgsFeature f;
170 while ( featureIterator.nextFeature( f ) )
171 {
172 if ( feedback->isCanceled() )
173 break;
174
175 if ( !exporter->addFeature( f, QgsFeatureSink::FastInsert ) )
176 feedback->reportError( exporter->errorMessage() );
177
178 feedback->setProgress( i * progressStep );
179 i++;
180 }
181 exporter->flushBuffer();
182
183 if ( exporter->errorCode() != Qgis::VectorExportResult::Success )
184 throw QgsProcessingException( QObject::tr( "Error exporting to PostGIS\n%1" ).arg( exporter->errorMessage() ) );
185
186 exporter.reset();
187
188 if ( !mGeomColumn.isEmpty() && mCreateIndex )
189 {
190 try
191 {
193 opt.geometryColumnName = mGeomColumn;
194 mConn->createSpatialIndex( mSchema, mTable, opt );
195 }
197 {
198 throw QgsProcessingException( QObject::tr( "Error creating spatial index:\n%1" ).arg( ex.what() ) );
199 }
200 }
201
202 try
203 {
204 mConn->vacuum( mSchema, mTable );
205 }
207 {
208 feedback->reportError( QObject::tr( "Error vacuuming table:\n{0}" ).arg( ex.what() ) );
209 }
210
211 QVariantMap outputs;
212 return outputs;
213}
@ Vector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
Definition qgis.h:3653
@ Success
No errors were encountered.
Definition qgis.h:1079
@ NoGeometry
No geometry.
Definition qgis.h:312
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:56
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition qgsfeedback.h:65
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:7485
The SpatialIndexOptions contains extra options relating to spatial index creation.
QString geometryColumnName
Specifies the name of the geometry column to create the index for.