void QgsComposerAttributeTableV2::setDisplayedFields( const QStringList& fields, bool refresh ) { QgsVectorLayer* source = sourceLayer(); if ( !source ) { return; } //rebuild columns list, taking only fields contained in supplied list qDeleteAll( mColumns ); mColumns.clear(); QgsFields layerFields = source->fields(); if ( !fields.isEmpty() ) { Q_FOREACH ( const QString& field, fields ) { int attrIdx = layerFields.lookupField( field ); if ( attrIdx < 0 ) continue; QString currentAlias = source->attributeDisplayName( attrIdx ); QgsComposerTableColumn* col = new QgsComposerTableColumn; col->setAttribute( layerFields.at( attrIdx ).name() ); col->setHeading( currentAlias ); mColumns.append( col ); }
QgsVirtualLayerDefinition QgsVirtualLayerDefinitionUtils::fromJoinedLayer( QgsVectorLayer *layer ) { QgsVirtualLayerDefinition def; QStringList leftJoins; QStringList columns; // add the geometry column if the layer is spatial if ( layer->isSpatial() ) columns << "t.geometry"; // look for the uid QgsFields fields = layer->dataProvider()->fields(); { QgsAttributeList pk = layer->dataProvider()->pkAttributeIndexes(); if ( pk.size() == 1 ) { def.setUid( fields.field( pk[0] ).name() ); } else { // find an uid name QString uid = QStringLiteral( "uid" ); while ( fields.lookupField( uid ) != -1 ) uid += QLatin1String( "_" ); // add "_" each time this name already exists // add a column columns << "t.rowid AS " + uid; def.setUid( uid ); } } const QgsFields providerFields = layer->dataProvider()->fields(); for ( const auto &f : providerFields ) { columns << "t.\"" + f.name() + "\""; } int joinIdx = 0; Q_FOREACH ( const QgsVectorLayerJoinInfo &join, layer->vectorJoins() ) { QString joinName = QStringLiteral( "j%1" ).arg( ++joinIdx ); QgsVectorLayer *joinedLayer = join.joinLayer(); if ( !joinedLayer ) continue; QString prefix = join.prefix().isEmpty() ? joinedLayer->name() + "_" : join.prefix(); leftJoins << QStringLiteral( "LEFT JOIN \"%1\" AS %2 ON t.\"%5\"=%2.\"%3\"" ).arg( joinedLayer->id(), joinName, join.joinFieldName(), join.targetFieldName() ); if ( join.joinFieldNamesSubset() ) { Q_FOREACH ( const QString &f, *join.joinFieldNamesSubset() ) { columns << joinName + ".\"" + f + "\" AS \"" + prefix + f + "\""; } } else {
void TestQgsFields::indexFromName() { QgsFields fields; QgsField field( QString( "testfield" ) ); field.setAlias( "testfieldAlias" ); fields.append( field ); QgsField field2( QString( "testfield2" ) ); fields.append( field2 ); QgsField field3( QString( "testfield3" ) ); fields.append( field3 ); QCOMPARE( fields.indexFromName( QString( "bad" ) ), -1 ); QCOMPARE( fields.lookupField( QString( "bad" ) ), -1 ); QCOMPARE( fields.indexFromName( QString( "testfield" ) ), 0 ); QCOMPARE( fields.lookupField( QString( "testfield" ) ), 0 ); QCOMPARE( fields.indexFromName( QString( "testfield3" ) ), 2 ); QCOMPARE( fields.lookupField( QString( "testfield3" ) ), 2 ); //indexFromName is case sensitive, fieldNameIndex isn't QCOMPARE( fields.indexFromName( QString( "teStFiEld2" ) ), -1 ); QCOMPARE( fields.lookupField( QString( "teStFiEld2" ) ), 1 ); //test that fieldNameIndex prefers exact case matches over case insensitive matches QgsField sameNameDifferentCase( QString( "teStFielD" ) ); fields.append( sameNameDifferentCase ); QCOMPARE( fields.lookupField( QString( "teStFielD" ) ), 3 ); //test that the alias is only matched with fieldNameIndex QCOMPARE( fields.indexFromName( "testfieldAlias" ), -1 ); QCOMPARE( fields.lookupField( "testfieldAlias" ), 0 ); QCOMPARE( fields.lookupField( "testfieldalias" ), 0 ); }
void QgsHeatmapRenderer::startRender( QgsRenderContext& context, const QgsFields& fields ) { Q_UNUSED( fields ); if ( !context.painter() ) { return; } // find out classification attribute index from name mWeightAttrNum = fields.lookupField( mWeightExpressionString ); if ( mWeightAttrNum == -1 ) { mWeightExpression.reset( new QgsExpression( mWeightExpressionString ) ); mWeightExpression->prepare( &context.expressionContext() ); } initializeValues( context ); return; }
void QgsVectorFieldSymbolLayer::startRender( QgsSymbolRenderContext& context ) { if ( mLineSymbol ) { mLineSymbol->startRender( context.renderContext(), context.fields() ); } QgsFields fields = context.fields(); if ( !fields.isEmpty() ) { mXIndex = fields.lookupField( mXAttribute ); mYIndex = fields.lookupField( mYAttribute ); } else { mXIndex = -1; mYIndex = -1; } }
QSet<int> QgsExpression::referencedAttributeIndexes( const QgsFields &fields ) const { if ( !d->mRootNode ) return QSet<int>(); const QSet<QString> referencedFields = d->mRootNode->referencedColumns(); QSet<int> referencedIndexes; for ( const QString &fieldName : referencedFields ) { if ( fieldName == QgsFeatureRequest::ALL_ATTRIBUTES ) { referencedIndexes = fields.allAttributesList().toSet(); break; } referencedIndexes << fields.lookupField( fieldName ); } return referencedIndexes; }
bool QgsProperty::prepare( const QgsExpressionContext &context ) const { if ( !d->active ) return true; switch ( d->type ) { case StaticProperty: return true; case FieldBasedProperty: { d.detach(); // cache field index to avoid subsequent lookups QgsFields f = context.fields(); d->cachedFieldIdx = f.lookupField( d->fieldName ); return true; } case ExpressionBasedProperty: { d.detach(); if ( !d->expression.prepare( &context ) ) { d->expressionReferencedCols.clear(); d->expressionPrepared = false; return false; } d->expressionPrepared = true; d->expressionReferencedCols = d->expression.referencedColumns(); return true; } case InvalidProperty: return true; } return false; }
void QgsGraduatedSymbolRenderer::startRender( QgsRenderContext &context, const QgsFields &fields ) { mCounting = context.rendererScale() == 0.0; // find out classification attribute index from name mAttrNum = fields.lookupField( mAttrName ); if ( mAttrNum == -1 ) { mExpression.reset( new QgsExpression( mAttrName ) ); mExpression->prepare( &context.expressionContext() ); } Q_FOREACH ( const QgsRendererRange &range, mRanges ) { if ( !range.symbol() ) continue; range.symbol()->startRender( context, fields ); } }
QgsVectorLayerImport::ImportError QgsDb2Provider::createEmptyLayer( const QString& uri, const QgsFields &fields, QgsWkbTypes::Type wkbType, const QgsCoordinateReferenceSystem& srs, bool overwrite, QMap<int, int> *oldToNewAttrIdxMap, QString *errorMessage, const QMap<QString, QVariant> *options ) { Q_UNUSED( options ); // populate members from the uri structure QgsDataSourceUri dsUri( uri ); QString connInfo = dsUri.connectionInfo(); QString errMsg; QString srsName; QgsDebugMsg( "uri: " + uri ); // connect to database QSqlDatabase db = QgsDb2Provider::getDatabase( connInfo, errMsg ); if ( !errMsg.isEmpty() ) { if ( errorMessage ) *errorMessage = errMsg; return QgsVectorLayerImport::ErrConnectionFailed; } // Get the SRS name using srid, needed to register the spatial column // srs->posgisSrid() seems to return the authority id which is // most often the EPSG id. Hopefully DB2 has defined an SRS using this // value as the srid / srs_id. If not, we are out of luck. QgsDebugMsg( "srs: " + srs.toWkt() ); long srid = srs.postgisSrid(); QgsDebugMsg( QString( "srid: %1" ).arg( srid ) ); if ( srid >= 0 ) { QSqlQuery query( db ); QString statement = QString( "SELECT srs_name FROM db2gse.st_spatial_reference_systems where srs_id=%1" ) .arg( srid ); QgsDebugMsg( statement ); if ( !query.exec( statement ) || !query.isActive() ) { QgsDebugMsg( query.lastError().text() ); } if ( query.next() ) { srsName = query.value( 0 ).toString(); QgsDebugMsg( QString( "srs_name: %1" ).arg( srsName ) ); } else { QgsDebugMsg( "Couldn't get srs_name from db2gse.st_spatial_reference_systems" ); } } QString schemaName = dsUri.schema().toUpper(); QString tableName = dsUri.table().toUpper(); QString fullName; if ( schemaName.isEmpty() ) { schemaName = dsUri.username().toUpper(); // set schema to user name } fullName = schemaName + "." + tableName; QString geometryColumn = dsUri.geometryColumn().toUpper(); QString primaryKey = dsUri.keyColumn().toUpper(); QString primaryKeyType; // TODO - this is a bad hack to cope with shapefiles. // The wkbType from the shapefile header is usually a multi-type // even if all the data is a single-type. If we create the column as // a multi-type, the insert will fail if the actual data is a single-type // due to type mismatch. // We could potentially defer adding the spatial column until addFeatures is // called the first time, but QgsVectorLayerImport doesn't pass the CRS/srid // information to the DB2 provider and we need this information to register // the spatial column. // This hack is problematic because the drag/drop will fail if the // actual data is a multi-type which is possible with a shapefile or // other data source. QgsWkbTypes::Type wkbTypeSingle; wkbTypeSingle = QgsWkbTypes::singleType( wkbType ); if ( wkbType != QgsWkbTypes::NoGeometry && geometryColumn.isEmpty() ) geometryColumn = "GEOM"; if ( primaryKey.isEmpty() ) primaryKey = "QGS_FID"; // get the pk's name and type // if no pk name was passed, define the new pk field name int fieldCount = fields.size(); if ( primaryKey.isEmpty() ) { int index = 0; QString pk = primaryKey = "QGS_FID"; for ( int i = 0; i < fieldCount; ++i ) { if ( fields.at( i ).name() == primaryKey ) { // it already exists, try again with a new name primaryKey = QString( "%1_%2" ).arg( pk ).arg( index++ ); i = 0; } } } else { // search for the passed field for ( int i = 0; i < fieldCount; ++i ) { if ( fields.at( i ).name() == primaryKey ) { // found, get the field type QgsField fld = fields.at( i ); if ( convertField( fld ) ) { primaryKeyType = fld.typeName(); } } } } QgsDebugMsg( "primaryKeyType: '" + primaryKeyType + "'" ); QString sql; QSqlQuery q = QSqlQuery( db ); q.setForwardOnly( true ); // get wkb type and dimension QString geometryType; int dim = 2; db2WkbTypeAndDimension( wkbTypeSingle, geometryType, dim ); QgsDebugMsg( QString( "wkbTypeSingle: %1; geometryType: %2" ).arg( wkbTypeSingle ).arg( geometryType ) ); if ( overwrite ) { // remove the old table with the same name sql = "DROP TABLE " + fullName; if ( !q.exec( sql ) ) { if ( q.lastError().number() != -206 ) // -206 is "not found" just ignore { QString lastError = q.lastError().text(); QgsDebugMsg( lastError ); if ( errorMessage ) { *errorMessage = lastError; } return QgsVectorLayerImport::ErrCreateLayer; } } } // add fields to the layer if ( oldToNewAttrIdxMap ) oldToNewAttrIdxMap->clear(); QString attr2Create = ""; if ( fields.size() > 0 ) { int offset = 0; // get the list of fields QgsDebugMsg( "PrimaryKey: '" + primaryKey + "'" ); for ( int i = 0; i < fieldCount; ++i ) { QgsField fld = fields.field( i ); QgsDebugMsg( QString( "i: %1; fldIdx: %2; offset: %3" ) .arg( i ).arg( fields.lookupField( fld.name() ) ).arg( offset ) ); if ( oldToNewAttrIdxMap && fld.name() == primaryKey ) { oldToNewAttrIdxMap->insert( i , 0 ); continue; } if ( fld.name() == geometryColumn ) { // Found a field with the same name of the geometry column. Skip it! continue; } QString db2Field = qgsFieldToDb2Field( fld ); if ( db2Field.isEmpty() ) { if ( errorMessage ) { *errorMessage = QObject::tr( "Unsupported type for field %1" ).arg( fld.name() ); } return QgsVectorLayerImport::ErrAttributeTypeUnsupported; } if ( oldToNewAttrIdxMap ) { oldToNewAttrIdxMap->insert( fields.lookupField( fld.name() ), offset++ ); } attr2Create += ',' + db2Field.toUpper(); } QgsDebugMsg( attr2Create ); if ( !geometryColumn.isEmpty() ) { sql = QString( // need to set specific geometry type "CREATE TABLE %1(%2 BIGINT NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY, " "%3 DB2GSE.%4 %5) " ) .arg( fullName, primaryKey, geometryColumn, geometryType, attr2Create ); } else { //geometryless table sql = QString( // need to set specific geometry type "CREATE TABLE %1.%2(%3 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS %4) " ) .arg( schemaName, tableName, primaryKey, attr2Create ); } QgsDebugMsg( sql ); if ( !q.exec( sql ) ) { QString lastError = q.lastError().text(); QgsDebugMsg( lastError ); if ( errorMessage ) { *errorMessage = lastError; } return QgsVectorLayerImport::ErrCreateLayer; } if ( !geometryColumn.isEmpty() ) { int computeExtents = 0; int msgCode = 0; int outCode; int outMsg; QVariant msgText( " " ); QSqlQuery query( db ); int db2Environment = ENV_LUW; // get the environment QgsDb2GeometryColumns gc( db ); int rc = gc.open( schemaName, tableName ); // returns SQLCODE if failure if ( rc == 0 ) { db2Environment = gc.db2Environment(); } if ( ENV_LUW == db2Environment ) { sql = QString( "CALL DB2GSE.ST_Register_Spatial_Column(?, ?, ?, ?, ?, ?, ?)" ); outCode = 5; outMsg = 6; } else // z/OS doesn't support 'computeExtents' parameter and has different schema { sql = QString( "CALL SYSPROC.ST_Register_Spatial_Column(?, ?, ?, ?, ?, ?)" ); outCode = 4; outMsg = 5; } query.prepare( sql ); query.bindValue( 0, schemaName ); query.bindValue( 1, tableName ); query.bindValue( 2, geometryColumn ); query.bindValue( 3, srsName ); if ( ENV_LUW == db2Environment ) { query.bindValue( 4, computeExtents ); } query.bindValue( outCode, msgCode, QSql::Out ); query.bindValue( outMsg, msgText, QSql::Out ); if ( !query.exec() ) { QgsDebugMsg( QString( "error: %1; sql: %2" ).arg( query.lastError().text(), query.lastQuery() ) ); } else { msgCode = query.boundValue( outCode ).toInt(); msgText = query.boundValue( outMsg ).toString(); // never gets a value... if ( 0 != msgCode ) { QgsDebugMsg( QString( "Register failed with code: %1; text: '%2'" ).arg( msgCode ).arg( msgText.toString() ) ); } else { QgsDebugMsg( "Register successful" ); } } QList<QVariant> list = query.boundValues().values(); for ( int i = 0; i < list.size(); ++i ) { QgsDebugMsg( QString( "i: %1; value: %2; type: %3" ) .arg( i ).arg( list.at( i ).toString().toLatin1().data() ).arg( list.at( i ).typeName() ) ); } } // clear any resources hold by the query q.clear(); q.setForwardOnly( true ); } QgsDebugMsg( "successfully created empty layer" ); return QgsVectorLayerImport::NoError; }