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