Skip to content
Permalink
Browse files
Merge pull request #1375 from nyalldawson/processing_postgis2
Some postgresql provider and PostGIS-related processing improvements and fixes (v2)
  • Loading branch information
jef-n committed May 21, 2014
2 parents 6df9d1c + ec3da40 commit e2c2575485f25f6ab8412b4a85ba882efe2ad74b
@@ -36,6 +36,7 @@
from processing.parameters.ParameterVector import ParameterVector
from processing.parameters.ParameterString import ParameterString
from processing.parameters.ParameterSelection import ParameterSelection
from processing.parameters.ParameterTableField import ParameterTableField
from processing.tools import dataobjects
import postgis_utils

@@ -50,6 +51,8 @@ class ImportIntoPostGIS(GeoAlgorithm):
CREATEINDEX = 'CREATEINDEX'
GEOMETRY_COLUMN = 'GEOMETRY_COLUMN'
LOWERCASE_NAMES = 'LOWERCASE_NAMES'
DROP_STRING_LENGTH = 'DROP_STRING_LENGTH'
PRIMARY_KEY = 'PRIMARY_KEY'

def getIcon(self):
return QIcon(os.path.dirname(__file__) + '/../../images/postgis.png')
@@ -60,6 +63,8 @@ def processAlgorithm(self, progress):
overwrite = self.getParameterValue(self.OVERWRITE)
createIndex = self.getParameterValue(self.CREATEINDEX)
convertLowerCase = self.getParameterValue(self.LOWERCASE_NAMES)
dropStringLength = self.getParameterValue(self.DROP_STRING_LENGTH)
primaryKeyField = self.getParameterValue(self.PRIMARY_KEY)
settings = QSettings()
mySettings = '/PostgreSQL/connections/' + connection
try:
@@ -87,15 +92,22 @@ def processAlgorithm(self, progress):
if not geomColumn:
geomColumn = 'the_geom'

uri = QgsDataSourceURI()
uri.setConnection(host, str(port), database, username, password)
uri.setDataSource(schema, table, geomColumn, '')

options = {}
if overwrite:
options['overwrite'] = True
if convertLowerCase:
options['lowercaseFieldNames'] = True
geomColumn = geomColumn.lower()
if dropStringLength:
options['dropStringConstraints'] = True

uri = QgsDataSourceURI()
uri.setConnection(host, str(port), database, username, password)
if primaryKeyField:
uri.setDataSource(schema, table, geomColumn, '', primaryKeyField)
else:
uri.setDataSource(schema, table, geomColumn, '')

layerUri = self.getParameterValue(self.INPUT)
layer = dataobjects.getObjectFromUri(layerUri)
(ret, errMsg) = QgsVectorLayerImport.importLayer(
@@ -133,10 +145,14 @@ def defineCharacteristics(self):
self.addParameter(ParameterString(self.SCHEMA, 'Schema (schema name)'))
self.addParameter(ParameterString(self.TABLENAME, 'Table to import to'
))
self.addParameter(ParameterTableField(self.PRIMARY_KEY, 'Primary key field',
self.INPUT, optional=True))
self.addParameter(ParameterString(self.GEOMETRY_COLUMN, 'Geometry column', 'the_geom'
))
self.addParameter(ParameterBoolean(self.OVERWRITE, 'Overwrite', True))
self.addParameter(ParameterBoolean(self.CREATEINDEX,
'Create spatial index', True))
self.addParameter(ParameterBoolean(self.LOWERCASE_NAMES,
'Convert field names to lowercase', False))
self.addParameter(ParameterBoolean(self.DROP_STRING_LENGTH,
'Drop length constraints on character fields', False))
@@ -2767,9 +2767,17 @@ bool QgsPostgresProvider::getGeometryDetails()
return mValid;
}

bool QgsPostgresProvider::convertField( QgsField &field )
bool QgsPostgresProvider::convertField( QgsField &field , const QMap<QString, QVariant>* options )
{
QString fieldType = "varchar"; //default to string
//determine field type to use for strings
QString stringFieldType = "varchar";
if ( options->contains( "dropStringConstraints" ) && options->value( "dropStringConstraints" ).toBool() )
{
//drop string length constraints by using PostgreSQL text type for strings
stringFieldType = "text";
}

QString fieldType = stringFieldType; //default to string
int fieldSize = field.length();
int fieldPrec = field.precision();
switch ( field.type() )
@@ -2788,7 +2796,7 @@ bool QgsPostgresProvider::convertField( QgsField &field )
break;

case QVariant::String:
fieldType = "varchar";
fieldType = stringFieldType;
fieldPrec = -1;
break;

@@ -2900,7 +2908,7 @@ QgsVectorLayerImport::ImportError QgsPostgresProvider::createEmptyLayer(
{
// found, get the field type
QgsField fld = fields[fldIdx];
if ( convertField( fld ) )
if ( convertField( fld, options ) )
{
primaryKeyType = fld.typeName();
}
@@ -2953,6 +2961,13 @@ QgsVectorLayerImport::ImportError QgsPostgresProvider::createEmptyLayer(
throw PGException( result );
}

if ( options->contains( "lowercaseFieldNames" ) && options->value( "lowercaseFieldNames" ).toBool() )
{
//convert primary key name to lowercase
//this must happen after determining the field type of the primary key
primaryKey = primaryKey.toLower();
}

sql = QString( "CREATE TABLE %1(%2 %3 PRIMARY KEY)" )
.arg( schemaTableName )
.arg( quotedIdentifier( primaryKey ) )
@@ -3032,14 +3047,11 @@ QgsVectorLayerImport::ImportError QgsPostgresProvider::createEmptyLayer(
for ( int fldIdx = 0; fldIdx < fields.count(); ++fldIdx )
{
QgsField fld = fields[fldIdx];
if ( fld.name() == primaryKey )
{
oldToNewAttrIdxMap->insert( fldIdx, 0 );
continue;
}

if ( fld.name() == geometryColumn )
{
//the "lowercaseFieldNames" option does not affect the name of the geometry column, so we perform
//this test before converting the field name to lowercase
QgsDebugMsg( "Found a field with the same name of the geometry column. Skip it!" );
continue;
}
@@ -3050,7 +3062,13 @@ QgsVectorLayerImport::ImportError QgsPostgresProvider::createEmptyLayer(
fld.setName( fld.name().toLower() );
}

if ( !convertField( fld ) )
if ( fld.name() == primaryKey )
{
oldToNewAttrIdxMap->insert( fldIdx, 0 );
continue;
}

if ( !convertField( fld, options ) )
{
if ( errorMessage )
*errorMessage = QObject::tr( "Unsupported type for field %1" ).arg( fld.name() );
@@ -47,7 +47,12 @@ class QgsPostgresProvider : public QgsVectorDataProvider

public:

/** Import a vector layer into the database */
/** Import a vector layer into the database
* @param options options for provider, specified via a map of option name
* to value. Valid options are lowercaseFieldNames (set to true to convert
* field names to lowercase), dropStringConstraints (set to true to remove
* length constraints on character fields).
*/
static QgsVectorLayerImport::ImportError createEmptyLayer(
const QString& uri,
const QgsFields &fields,
@@ -324,7 +329,7 @@ class QgsPostgresProvider : public QgsVectorDataProvider
bool loadFields();

/** convert a QgsField to work with PG */
static bool convertField( QgsField &field );
static bool convertField( QgsField &field, const QMap<QString, QVariant> *options = 0 );

/**Parses the enum_range of an attribute and inserts the possible values into a stringlist
@param enumValues the stringlist where the values are appended

0 comments on commit e2c2575

Please sign in to comment.