Skip to content
Permalink
Browse files

[feature][processing] Add dedicated parameter type for database schemas

Allows selection from the existing database schema for a specific
database provider connection (the provider must implement the connections API)
  • Loading branch information
nyalldawson committed Mar 10, 2020
1 parent 465f8a5 commit 93c917f7b6e93bae26a16078ace44879ff3930d8
@@ -874,6 +874,13 @@ Evaluates the parameter with matching ``name`` to a color, or returns an invalid
%Docstring
Evaluates the parameter with matching ``name`` to a connection name string.

.. versionadded:: 3.14
%End

QString parameterAsSchema( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to a database schema name string.

.. versionadded:: 3.14
%End

@@ -199,6 +199,8 @@ their acceptable ranges, defaults, etc.
sipType = sipType_QgsProcessingParameterDateTime;
else if ( sipCpp->type() == QgsProcessingParameterProviderConnection::typeName() )
sipType = sipType_QgsProcessingParameterProviderConnection;
else if ( sipCpp->type() == QgsProcessingParameterDatabaseSchema::typeName() )
sipType = sipType_QgsProcessingParameterDatabaseSchema;
else
sipType = nullptr;
%End
@@ -1203,6 +1205,20 @@ Evaluates the parameter with matching ``definition`` to a connection name string
%Docstring
Evaluates the parameter with matching ``definition`` and ``value`` to a connection name string.

.. versionadded:: 3.14
%End

static QString parameterAsSchema( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``definition`` to a database schema name.

.. versionadded:: 3.14
%End

static QString parameterAsSchema( const QgsProcessingParameterDefinition *definition, const QVariant &value, const QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``definition`` and ``value`` to a database schema name.

.. versionadded:: 3.14
%End

@@ -3689,6 +3705,79 @@ Creates a new parameter using the definition from a script code.
};


class QgsProcessingParameterDatabaseSchema : QgsProcessingParameterDefinition
{
%Docstring
A database schema parameter for processing algorithms, allowing users to select from existing schemas
on a registered database connection.

QgsProcessingParameterDatabaseSchema should be evaluated by calling :py:func:`QgsProcessingAlgorithm.parameterAsSchema()`

.. versionadded:: 3.14
%End

%TypeHeaderCode
#include "qgsprocessingparameters.h"
%End
public:

QgsProcessingParameterDatabaseSchema( const QString &name, const QString &description, const QString &connectionParameterName = QString(), const QVariant &defaultValue = QVariant(),
bool optional = false );
%Docstring
Constructor for QgsProcessingParameterDatabaseSchema.

The ``connectionParameterName`` specifies the name of the parent QgsProcessingParameterProviderConnection parameter.

.. warning::

The provider must support the connection API methods in its QgsProviderMetadata implementation
in order for the model to work correctly. This is only implemented for a subset of current data providers.
%End

static QString typeName();
%Docstring
Returns the type name for the parameter class.
%End
virtual QgsProcessingParameterDefinition *clone() const /Factory/;

virtual QString type() const;
virtual bool checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context = 0 ) const;

virtual QString valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const;

virtual QString asScriptCode() const;

virtual QString asPythonString( QgsProcessing::PythonOutputType outputType = QgsProcessing::PythonQgsProcessingAlgorithmSubclass ) const;

virtual QVariantMap toVariantMap() const;

virtual bool fromVariantMap( const QVariantMap &map );

virtual QStringList dependsOnOtherParameters() const;


QString parentConnectionParameterName() const;
%Docstring
Returns the name of the parent connection parameter, or an empty string if this is not set.

.. seealso:: :py:func:`setParentConnectionParameterName`
%End

void setParentConnectionParameterName( const QString &name );
%Docstring
Sets the ``name`` of the parent connection parameter. Use an empty string if this is not required.

.. seealso:: :py:func:`parentConnectionParameterName`
%End

static QgsProcessingParameterDatabaseSchema *fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition ) /Factory/;
%Docstring
Creates a new parameter using the definition from a script code.
%End

};





@@ -739,6 +739,11 @@ QDateTime QgsProcessingAlgorithm::parameterAsDateTime( const QVariantMap &parame
return QgsProcessingParameters::parameterAsDateTime( parameterDefinition( name ), parameters, context );
}

QString QgsProcessingAlgorithm::parameterAsSchema( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context )
{
return QgsProcessingParameters::parameterAsSchema( parameterDefinition( name ), parameters, context );
}

QString QgsProcessingAlgorithm::invalidSourceError( const QVariantMap &parameters, const QString &name )
{
if ( !parameters.contains( name ) )
@@ -864,6 +864,13 @@ class CORE_EXPORT QgsProcessingAlgorithm
*/
QString parameterAsConnectionName( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );

/**
* Evaluates the parameter with matching \a name to a database schema name string.
*
* \since QGIS 3.14
*/
QString parameterAsSchema( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );

/**
* Evaluates the parameter with matching \a name to a DateTime, or returns an invalid date time if the parameter was not set.
*
@@ -1789,6 +1789,21 @@ QString QgsProcessingParameters::parameterAsConnectionName( const QgsProcessingP
return parameterAsString( definition, value, context );
}

QString QgsProcessingParameters::parameterAsSchema( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context )
{
if ( !definition )
return QString();

return parameterAsConnectionName( definition, parameters.value( definition->name() ), context );
}

QString QgsProcessingParameters::parameterAsSchema( const QgsProcessingParameterDefinition *definition, const QVariant &value, const QgsProcessingContext &context )
{
// for now it's just treated identical to strings, but in future we may want flexibility to amend this (e.g. if we want to embed connection details into the schema
// parameter values, such as via a delimiter separated string)
return parameterAsString( definition, value, context );
}

QgsProcessingParameterDefinition *QgsProcessingParameters::parameterFromVariantMap( const QVariantMap &map )
{
QString type = map.value( QStringLiteral( "parameter_type" ) ).toString();
@@ -1957,6 +1972,8 @@ QgsProcessingParameterDefinition *QgsProcessingParameters::parameterFromScriptCo
return QgsProcessingParameterDateTime::fromScriptCode( name, description, isOptional, definition );
else if ( type == QStringLiteral( "providerconnection" ) )
return QgsProcessingParameterProviderConnection::fromScriptCode( name, description, isOptional, definition );
else if ( type == QStringLiteral( "databaseschema" ) )
return QgsProcessingParameterDatabaseSchema::fromScriptCode( name, description, isOptional, definition );

return nullptr;
}
@@ -6628,3 +6645,131 @@ QgsProcessingParameterProviderConnection *QgsProcessingParameterProviderConnecti
return new QgsProcessingParameterProviderConnection( name, description, provider, defaultValue, isOptional );
}


//
// QgsProcessingParameterDatabaseSchema
//

QgsProcessingParameterDatabaseSchema::QgsProcessingParameterDatabaseSchema( const QString &name, const QString &description, const QString &parentLayerParameterName, const QVariant &defaultValue, bool optional )
: QgsProcessingParameterDefinition( name, description, defaultValue, optional )
, mParentConnectionParameterName( parentLayerParameterName )
{

}


QgsProcessingParameterDefinition *QgsProcessingParameterDatabaseSchema::clone() const
{
return new QgsProcessingParameterDatabaseSchema( *this );
}

bool QgsProcessingParameterDatabaseSchema::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
{
if ( !input.isValid() && !mDefault.isValid() )
return mFlags & FlagOptional;

if ( ( input.type() == QVariant::String && input.toString().isEmpty() )
|| ( !input.isValid() && mDefault.type() == QVariant::String && mDefault.toString().isEmpty() ) )
return mFlags & FlagOptional;

return true;
}

QString QgsProcessingParameterDatabaseSchema::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
{
if ( !value.isValid() )
return QStringLiteral( "None" );

if ( value.canConvert<QgsProperty>() )
return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );

return QgsProcessingUtils::stringToPythonLiteral( value.toString() );
}

QString QgsProcessingParameterDatabaseSchema::asScriptCode() const
{
QString code = QStringLiteral( "##%1=" ).arg( mName );
if ( mFlags & FlagOptional )
code += QStringLiteral( "optional " );
code += QStringLiteral( "databaseschema " );

code += mParentConnectionParameterName + ' ';

code += mDefault.toString();
return code.trimmed();
}

QString QgsProcessingParameterDatabaseSchema::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
{
switch ( outputType )
{
case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
{
QString code = QStringLiteral( "QgsProcessingParameterDatabaseSchema('%1', '%2'" ).arg( name(), description() );
if ( mFlags & FlagOptional )
code += QStringLiteral( ", optional=True" );

code += QStringLiteral( ", connectionParameterName='%1'" ).arg( mParentConnectionParameterName );
QgsProcessingContext c;
code += QStringLiteral( ", defaultValue=%1" ).arg( valueAsPythonString( mDefault, c ) );

code += ')';

return code;
}
}
return QString();
}

QStringList QgsProcessingParameterDatabaseSchema::dependsOnOtherParameters() const
{
QStringList depends;
if ( !mParentConnectionParameterName.isEmpty() )
depends << mParentConnectionParameterName;
return depends;
}

QString QgsProcessingParameterDatabaseSchema::parentConnectionParameterName() const
{
return mParentConnectionParameterName;
}

void QgsProcessingParameterDatabaseSchema::setParentConnectionParameterName( const QString &name )
{
mParentConnectionParameterName = name;
}

QVariantMap QgsProcessingParameterDatabaseSchema::toVariantMap() const
{
QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
map.insert( QStringLiteral( "mParentLayerParameterName" ), mParentConnectionParameterName );
return map;
}

bool QgsProcessingParameterDatabaseSchema::fromVariantMap( const QVariantMap &map )
{
QgsProcessingParameterDefinition::fromVariantMap( map );
mParentConnectionParameterName = map.value( QStringLiteral( "mParentLayerParameterName" ) ).toString();
return true;
}

QgsProcessingParameterDatabaseSchema *QgsProcessingParameterDatabaseSchema::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
{
QString parent;
QString def = definition;

QRegularExpression re( QStringLiteral( "(.*?)\\s+(.*)$" ) );
QRegularExpressionMatch m = re.match( def );
if ( m.hasMatch() )
{
parent = m.captured( 1 ).trimmed();
def = m.captured( 2 );
}
else
{
parent = def;
def.clear();
}

return new QgsProcessingParameterDatabaseSchema( name, description, parent, def.isEmpty() ? QVariant() : def, isOptional );
}

1 comment on commit 93c917f

@havatv

This comment has been minimized.

Copy link
Contributor

@havatv havatv commented on 93c917f Mar 14, 2020

Great addition!
It would be nice to have an ALG decorator for it. Could it be added to python/processing/algfactory.py (and python/plugins/processing/core/parameters.py)?

Please sign in to comment.
You can’t perform that action at this time.