bool QgsOgrLayerItem::setCrs( QgsCoordinateReferenceSystem crs ) { QgsDebugMsg( "mPath = " + mPath ); OGRRegisterAll(); OGRSFDriverH hDriver; OGRDataSourceH hDataSource = OGROpen( TO8F( mPath ), true, &hDriver ); if ( !hDataSource ) return false; QString driverName = OGR_Dr_GetName( hDriver ); OGR_DS_Destroy( hDataSource ); // we are able to assign CRS only to shapefiles :-( if ( driverName == "ESRI Shapefile" ) { QString layerName = mPath.left( mPath.indexOf( ".shp", Qt::CaseInsensitive ) ); QString wkt = crs.toWkt(); // save ordinary .prj file OGRSpatialReferenceH hSRS = OSRNewSpatialReference( wkt.toLocal8Bit().data() ); OSRMorphToESRI( hSRS ); // this is the important stuff for shapefile .prj char* pszOutWkt = NULL; OSRExportToWkt( hSRS, &pszOutWkt ); QFile prjFile( layerName + ".prj" ); if ( prjFile.open( QIODevice::WriteOnly ) ) { QTextStream prjStream( &prjFile ); prjStream << pszOutWkt << endl; prjFile.close(); } else { QgsMessageLog::logMessage( tr( "Couldn't open file %1.prj" ).arg( layerName ), tr( "OGR" ) ); return false; } OSRDestroySpatialReference( hSRS ); CPLFree( pszOutWkt ); // save qgis-specific .qpj file (maybe because of better wkt compatibility?) QFile qpjFile( layerName + ".qpj" ); if ( qpjFile.open( QIODevice::WriteOnly ) ) { QTextStream qpjStream( &qpjFile ); qpjStream << wkt.toLocal8Bit().data() << endl; qpjFile.close(); } else { QgsMessageLog::logMessage( tr( "Couldn't open file %1.qpj" ).arg( layerName ), tr( "OGR" ) ); return false; } return true; } // It it is impossible to assign a crs to an existing layer // No OGR_L_SetSpatialRef : http://trac.osgeo.org/gdal/ticket/4032 return false; }
void QgsGrassNewMapset::setCurrentRegion() { QgsDebugMsg( "entered" ); QgsRectangle ext = mIface->mapCanvas()->extent(); QgsCoordinateReferenceSystem srs = mIface->mapCanvas()->mapSettings().destinationCrs(); QgsDebugMsg( "srs = " + srs.toWkt() ); std::vector<QgsPoint> points; // TODO: this is not perfect points.push_back( QgsPoint( ext.xMinimum(), ext.yMinimum() ) ); points.push_back( QgsPoint( ext.xMaximum(), ext.yMaximum() ) ); // TODO add a method, this code is copy-paste from setSelectedRegion if ( srs.isValid() && mCrs.isValid() && srs.srsid() != mCrs.srsid() ) { QgsCoordinateTransform trans( srs, mCrs ); bool ok = true; for ( int i = 0; i < 2; i++ ) { try { points[i] = trans.transform( points[i] ); } catch ( QgsCsException &cse ) { Q_UNUSED( cse ); QgsDebugMsg( "Cannot transform point" ); ok = false; break; } } if ( !ok ) { QgsGrass::warning( tr( "Cannot reproject region" ) ); return; } } mNorthLineEdit->setText( QString::number( points[1].y() ) ); mSouthLineEdit->setText( QString::number( points[0].y() ) ); mEastLineEdit->setText( QString::number( points[1].x() ) ); mWestLineEdit->setText( QString::number( points[0].x() ) ); mRegionModified = true; checkRegion(); drawRegion(); QgsDebugMsg( "setCurrentRegion - End" ); }
void QgsGrassNewMapset::setGrassRegionDefaults() { QgsDebugMsg( QString( "mCellHead.proj = %1" ).arg( mCellHead.proj ) ); QgsCoordinateReferenceSystem srs = mIface->mapCanvas()->mapSettings().destinationCrs(); QgsDebugMsg( "srs = " + srs.toWkt() ); QgsRectangle ext = mIface->mapCanvas()->extent(); bool extSet = false; if ( ext.xMinimum() < ext.xMaximum() && ext.yMinimum() < ext.yMaximum() ) { extSet = true; } if ( extSet && ( mNoProjRadioButton->isChecked() || ( mProjRadioButton->isChecked() && srs.srsid() == mProjectionSelector->selectedCrsId() ) ) ) { mNorthLineEdit->setText( QString::number( ext.yMaximum() ) ); mSouthLineEdit->setText( QString::number( ext.yMinimum() ) ); mEastLineEdit->setText( QString::number( ext.xMaximum() ) ); mWestLineEdit->setText( QString::number( ext.xMinimum() ) ); } else if ( mCellHead.proj == PROJECTION_XY ) { mNorthLineEdit->setText( "1000" ); mSouthLineEdit->setText( "0" ); mEastLineEdit->setText( "1000" ); mWestLineEdit->setText( "0" ); } else if ( mCellHead.proj == PROJECTION_LL ) { mNorthLineEdit->setText( "90" ); mSouthLineEdit->setText( "-90" ); mEastLineEdit->setText( "180" ); mWestLineEdit->setText( "-180" ); } else { mNorthLineEdit->setText( "100000" ); mSouthLineEdit->setText( "-100000" ); mEastLineEdit->setText( "100000" ); mWestLineEdit->setText( "-100000" ); } mRegionModified = false; }
bool QgsGdalLayerItem::setCrs( const QgsCoordinateReferenceSystem &crs ) { GDALDatasetH hDS = GDALOpen( mPath.toUtf8().constData(), GA_Update ); if ( !hDS ) return false; QString wkt = crs.toWkt(); if ( GDALSetProjection( hDS, wkt.toLocal8Bit().data() ) != CE_None ) { GDALClose( hDS ); QgsDebugMsg( "Could not set CRS" ); return false; } GDALClose( hDS ); return true; }
Q_NOWARN_DEPRECATED_POP bool QgsOgrLayerItem::setCrs( QgsCoordinateReferenceSystem crs ) { if ( !( mCapabilities & SetCrs ) ) return false; QString layerName = mPath.left( mPath.indexOf( ".shp", Qt::CaseInsensitive ) ); QString wkt = crs.toWkt(); // save ordinary .prj file OGRSpatialReferenceH hSRS = OSRNewSpatialReference( wkt.toLocal8Bit().data() ); OSRMorphToESRI( hSRS ); // this is the important stuff for shapefile .prj char* pszOutWkt = nullptr; OSRExportToWkt( hSRS, &pszOutWkt ); QFile prjFile( layerName + ".prj" ); if ( prjFile.open( QIODevice::WriteOnly ) ) { QTextStream prjStream( &prjFile ); prjStream << pszOutWkt << endl; prjFile.close(); } else { QgsMessageLog::logMessage( tr( "Couldn't open file %1.prj" ).arg( layerName ), tr( "OGR" ) ); return false; } OSRDestroySpatialReference( hSRS ); CPLFree( pszOutWkt ); // save qgis-specific .qpj file (maybe because of better wkt compatibility?) QFile qpjFile( layerName + ".qpj" ); if ( qpjFile.open( QIODevice::WriteOnly ) ) { QTextStream qpjStream( &qpjFile ); qpjStream << wkt.toLocal8Bit().data() << endl; qpjFile.close(); } else { QgsMessageLog::logMessage( tr( "Couldn't open file %1.qpj" ).arg( layerName ), tr( "OGR" ) ); return false; } return true; }
bool QgsGdalLayerItem::setCrs( QgsCoordinateReferenceSystem crs ) { QgsDebugMsg( "mPath = " + mPath ); GDALAllRegister(); GDALDatasetH hDS = GDALOpen( TO8F( mPath ), GA_Update ); if ( !hDS ) return false; QString wkt = crs.toWkt(); if ( GDALSetProjection( hDS, wkt.toLocal8Bit().data() ) != CE_None ) { QgsDebugMsg( "Could not set CRS" ); return false; } GDALClose( hDS ); return true; }
QgsCoordinateReferenceSystem GRASS_EXPORT QgsGrass::crs( QString gisdbase, QString location ) { QgsDebugMsg( QString( "gisdbase = %1 location = %2" ).arg( gisdbase ).arg( location ) ); QgsCoordinateReferenceSystem crs = QgsCoordinateReferenceSystem(); try { QString wkt = QgsGrass::getInfo( "proj", gisdbase, location ); QgsDebugMsg( "wkt: " + wkt ); crs.createFromWkt( wkt ); QgsDebugMsg( "crs.toWkt: " + crs.toWkt() ); } catch ( QgsGrass::Exception &e ) { QMessageBox::warning( 0, QObject::tr( "Warning" ), QObject::tr( "Cannot get projection " ) + "\n" + e.what() ); } return crs; }
void QgsRasterFileWriter::createVRT( int xSize, int ySize, const QgsCoordinateReferenceSystem& crs, double* geoTransform, QGis::DataType type, QList<bool> destHasNoDataValueList, QList<double> destNoDataValueList ) { mVRTDocument.clear(); QDomElement VRTDatasetElem = mVRTDocument.createElement( "VRTDataset" ); //xsize / ysize VRTDatasetElem.setAttribute( "rasterXSize", xSize ); VRTDatasetElem.setAttribute( "rasterYSize", ySize ); mVRTDocument.appendChild( VRTDatasetElem ); //CRS QDomElement SRSElem = mVRTDocument.createElement( "SRS" ); QDomText crsText = mVRTDocument.createTextNode( crs.toWkt() ); SRSElem.appendChild( crsText ); VRTDatasetElem.appendChild( SRSElem ); //geotransform if ( geoTransform ) { QDomElement geoTransformElem = mVRTDocument.createElement( "GeoTransform" ); QString geoTransformString = QString::number( geoTransform[0] ) + ", " + QString::number( geoTransform[1] ) + ", " + QString::number( geoTransform[2] ) + ", " + QString::number( geoTransform[3] ) + ", " + QString::number( geoTransform[4] ) + ", " + QString::number( geoTransform[5] ); QDomText geoTransformText = mVRTDocument.createTextNode( geoTransformString ); geoTransformElem.appendChild( geoTransformText ); VRTDatasetElem.appendChild( geoTransformElem ); } int nBands; if ( mMode == Raw ) { nBands = mInput->bandCount(); } else { nBands = 4; } QStringList colorInterp; colorInterp << "Red" << "Green" << "Blue" << "Alpha"; QMap<QGis::DataType, QString> dataTypes; dataTypes.insert( QGis::Byte, "Byte" ); dataTypes.insert( QGis::UInt16, "UInt16" ); dataTypes.insert( QGis::Int16, "Int16" ); dataTypes.insert( QGis::UInt32, "Int32" ); dataTypes.insert( QGis::Float32, "Float32" ); dataTypes.insert( QGis::Float64, "Float64" ); dataTypes.insert( QGis::CInt16, "CInt16" ); dataTypes.insert( QGis::CInt32, "CInt32" ); dataTypes.insert( QGis::CFloat32, "CFloat32" ); dataTypes.insert( QGis::CFloat64, "CFloat64" ); for ( int i = 1; i <= nBands; i++ ) { QDomElement VRTBand = mVRTDocument.createElement( "VRTRasterBand" ); VRTBand.setAttribute( "band", QString::number( i ) ); QString dataType = dataTypes.value( type ); VRTBand.setAttribute( "dataType", dataType ); if ( mMode == Image ) { VRTBand.setAttribute( "dataType", "Byte" ); QDomElement colorInterpElement = mVRTDocument.createElement( "ColorInterp" ); QDomText interpText = mVRTDocument.createTextNode( colorInterp.value( i - 1 ) ); colorInterpElement.appendChild( interpText ); VRTBand.appendChild( colorInterpElement ); } if ( !destHasNoDataValueList.isEmpty() && destHasNoDataValueList.value( i - 1 ) ) { VRTBand.setAttribute( "NoDataValue", QString::number( destNoDataValueList.value( i - 1 ) ) ); } mVRTBands.append( VRTBand ); VRTDatasetElem.appendChild( VRTBand ); } }
bool QgsNewGeoPackageLayerDialog::apply() { QString fileName( mDatabase->filePath() ); if ( !fileName.endsWith( QLatin1String( ".gpkg" ), Qt::CaseInsensitive ) ) fileName += QLatin1String( ".gpkg" ); bool createNewDb = false; if ( QFile( fileName ).exists( fileName ) ) { bool overwrite = false; switch ( mBehavior ) { case Prompt: { QMessageBox msgBox; msgBox.setIcon( QMessageBox::Question ); msgBox.setWindowTitle( tr( "The File Already Exists." ) ); msgBox.setText( tr( "Do you want to overwrite the existing file with a new database or add a new layer to it?" ) ); QPushButton *overwriteButton = msgBox.addButton( tr( "Overwrite" ), QMessageBox::ActionRole ); QPushButton *addNewLayerButton = msgBox.addButton( tr( "Add new layer" ), QMessageBox::ActionRole ); msgBox.setStandardButtons( QMessageBox::Cancel ); msgBox.setDefaultButton( addNewLayerButton ); bool cancel = false; if ( property( "hideDialogs" ).toBool() ) { overwrite = property( "question_existing_db_answer_overwrite" ).toBool(); if ( !overwrite ) cancel = !property( "question_existing_db_answer_add_new_layer" ).toBool(); } else { int ret = msgBox.exec(); if ( ret == QMessageBox::Cancel ) cancel = true; if ( msgBox.clickedButton() == overwriteButton ) overwrite = true; } if ( cancel ) { return false; } break; } case Overwrite: overwrite = true; break; case AddNewLayer: overwrite = false; break; } if ( overwrite ) { QFile( fileName ).remove(); createNewDb = true; } } else { createNewDb = true; } OGRSFDriverH hGpkgDriver = OGRGetDriverByName( "GPKG" ); if ( !hGpkgDriver ) { if ( !property( "hideDialogs" ).toBool() ) QMessageBox::critical( this, tr( "Layer creation failed" ), tr( "GeoPackage driver not found" ) ); return false; } gdal::ogr_datasource_unique_ptr hDS; if ( createNewDb ) { hDS.reset( OGR_Dr_CreateDataSource( hGpkgDriver, fileName.toUtf8().constData(), nullptr ) ); if ( !hDS ) { QString msg( tr( "Creation of database failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ) ); if ( !property( "hideDialogs" ).toBool() ) QMessageBox::critical( this, tr( "Layer creation failed" ), msg ); return false; } } else { OGRSFDriverH hDriver = nullptr; hDS.reset( OGROpen( fileName.toUtf8().constData(), true, &hDriver ) ); if ( !hDS ) { QString msg( tr( "Opening of database failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ) ); if ( !property( "hideDialogs" ).toBool() ) QMessageBox::critical( this, tr( "Layer creation failed" ), msg ); return false; } if ( hDriver != hGpkgDriver ) { QString msg( tr( "Opening of file succeeded, but this is not a GeoPackage database" ) ); if ( !property( "hideDialogs" ).toBool() ) QMessageBox::critical( this, tr( "Layer creation failed" ), msg ); return false; } } QString tableName( mTableNameEdit->text() ); bool overwriteTable = false; if ( OGR_DS_GetLayerByName( hDS.get(), tableName.toUtf8().constData() ) ) { if ( property( "hideDialogs" ).toBool() ) { overwriteTable = property( "question_existing_layer_answer_overwrite" ).toBool(); } else if ( QMessageBox::question( this, tr( "Existing layer" ), tr( "A table with the same name already exists. Do you want to overwrite it?" ), QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) == QMessageBox::Yes ) { overwriteTable = true; } if ( !overwriteTable ) { return false; } } QString layerIdentifier( mLayerIdentifierEdit->text() ); QString layerDescription( mLayerDescriptionEdit->text() ); OGRwkbGeometryType wkbType = static_cast<OGRwkbGeometryType> ( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() ); // z-coordinate & m-value. if ( mGeometryWithZCheckBox->isChecked() ) wkbType = OGR_GT_SetZ( wkbType ); if ( mGeometryWithMCheckBox->isChecked() ) wkbType = OGR_GT_SetM( wkbType ); OGRSpatialReferenceH hSRS = nullptr; // consider spatial reference system of the layer QgsCoordinateReferenceSystem srs = mCrsSelector->crs(); if ( wkbType != wkbNone && srs.isValid() ) { QString srsWkt = srs.toWkt(); hSRS = OSRNewSpatialReference( srsWkt.toLocal8Bit().data() ); } // Set options char **options = nullptr; if ( overwriteTable ) options = CSLSetNameValue( options, "OVERWRITE", "YES" ); if ( !layerIdentifier.isEmpty() ) options = CSLSetNameValue( options, "IDENTIFIER", layerIdentifier.toUtf8().constData() ); if ( !layerDescription.isEmpty() ) options = CSLSetNameValue( options, "DESCRIPTION", layerDescription.toUtf8().constData() ); QString featureId( mFeatureIdColumnEdit->text() ); if ( !featureId.isEmpty() ) options = CSLSetNameValue( options, "FID", featureId.toUtf8().constData() ); QString geometryColumn( mGeometryColumnEdit->text() ); if ( wkbType != wkbNone && !geometryColumn.isEmpty() ) options = CSLSetNameValue( options, "GEOMETRY_COLUMN", geometryColumn.toUtf8().constData() ); if ( wkbType != wkbNone ) options = CSLSetNameValue( options, "SPATIAL_INDEX", mCheckBoxCreateSpatialIndex->isChecked() ? "YES" : "NO" ); OGRLayerH hLayer = OGR_DS_CreateLayer( hDS.get(), tableName.toUtf8().constData(), hSRS, wkbType, options ); CSLDestroy( options ); if ( hSRS ) OSRRelease( hSRS ); if ( !hLayer ) { QString msg( tr( "Creation of layer failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ) ); if ( !property( "hideDialogs" ).toBool() ) QMessageBox::critical( this, tr( "Layer creation failed" ), msg ); return false; } QTreeWidgetItemIterator it( mAttributeView ); while ( *it ) { QString fieldName( ( *it )->text( 0 ) ); QString fieldType( ( *it )->text( 1 ) ); QString fieldWidth( ( *it )->text( 2 ) ); OGRFieldType ogrType( OFTString ); if ( fieldType == QLatin1String( "text" ) ) ogrType = OFTString; else if ( fieldType == QLatin1String( "integer" ) ) ogrType = OFTInteger; else if ( fieldType == QLatin1String( "integer64" ) ) ogrType = OFTInteger64; else if ( fieldType == QLatin1String( "real" ) ) ogrType = OFTReal; else if ( fieldType == QLatin1String( "date" ) ) ogrType = OFTDate; else if ( fieldType == QLatin1String( "datetime" ) ) ogrType = OFTDateTime; int ogrWidth = fieldWidth.toInt(); gdal::ogr_field_def_unique_ptr fld( OGR_Fld_Create( fieldName.toUtf8().constData(), ogrType ) ); OGR_Fld_SetWidth( fld.get(), ogrWidth ); if ( OGR_L_CreateField( hLayer, fld.get(), true ) != OGRERR_NONE ) { if ( !property( "hideDialogs" ).toBool() ) { QMessageBox::critical( this, tr( "Layer creation failed" ), tr( "Creation of field %1 failed (OGR error: %2)" ) .arg( fieldName, QString::fromUtf8( CPLGetLastErrorMsg() ) ) ); } return false; } ++it; } // In GDAL >= 2.0, the driver implements a deferred creation strategy, so // issue a command that will force table creation CPLErrorReset(); OGR_L_ResetReading( hLayer ); if ( CPLGetLastErrorType() != CE_None ) { QString msg( tr( "Creation of layer failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ) ); if ( !property( "hideDialogs" ).toBool() ) QMessageBox::critical( this, tr( "Layer creation failed" ), msg ); return false; } hDS.reset(); QString uri( QStringLiteral( "%1|layername=%2" ).arg( fileName, tableName ) ); QString userVisiblelayerName( layerIdentifier.isEmpty() ? tableName : layerIdentifier ); QgsVectorLayer *layer = new QgsVectorLayer( uri, userVisiblelayerName, QStringLiteral( "ogr" ) ); if ( layer->isValid() ) { // register this layer with the central layers registry QList<QgsMapLayer *> myList; myList << layer; //addMapLayers returns a list of all successfully added layers //so we compare that to our original list. if ( myList == QgsProject::instance()->addMapLayers( myList ) ) return true; } else { if ( !property( "hideDialogs" ).toBool() ) QMessageBox::critical( this, tr( "Invalid Layer" ), tr( "%1 is an invalid layer and cannot be loaded." ).arg( tableName ) ); delete layer; } return false; }
QgsDb2Provider::QgsDb2Provider( QString uri ) : QgsVectorDataProvider( uri ) , mNumberFeatures( 0 ) , mEnvironment( ENV_LUW ) , mWkbType( QgsWkbTypes::Unknown ) { QgsDebugMsg( "uri: " + uri ); QgsDataSourceUri anUri = QgsDataSourceUri( uri ); if ( !anUri.srid().isEmpty() ) mSRId = anUri.srid().toInt(); else mSRId = -1; if ( 0 != anUri.wkbType() ) { mWkbType = anUri.wkbType(); } QgsDebugMsg( QString( "mWkbType: %1" ).arg( mWkbType ) ); QgsDebugMsg( QString( "new mWkbType: %1" ).arg( anUri.wkbType() ) ); mValid = true; mSkipFailures = false; int dim; // Not used db2WkbTypeAndDimension( mWkbType, mGeometryColType, dim ); // Get DB2 geometry type name mFidColName = anUri.keyColumn().toUpper(); QgsDebugMsg( "mFidColName " + mFidColName ); mExtents = anUri.param( "extents" ); QgsDebugMsg( "mExtents " + mExtents ); mUseEstimatedMetadata = anUri.useEstimatedMetadata(); QgsDebugMsg( QString( "mUseEstimatedMetadata: '%1'" ).arg( mUseEstimatedMetadata ) ); mSqlWhereClause = anUri.sql(); QString errMsg; mDatabase = getDatabase( uri, errMsg ); mConnInfo = anUri.connectionInfo(); QgsCoordinateReferenceSystem layerCrs = crs(); QgsDebugMsg( "CRS: " + layerCrs.toWkt() ); if ( !errMsg.isEmpty() ) { setLastError( errMsg ); QgsDebugMsg( mLastError ); mValid = false; return; } // Create a query for default connection mQuery = QSqlQuery( mDatabase ); mSchemaName = anUri.schema(); mTableName = anUri.table().toUpper(); QStringList sl = mTableName.split( '.' ); if ( sl.length() == 2 ) // Never seems to be the case { mSchemaName = sl[0]; mTableName = sl[1]; } if ( mSchemaName.isEmpty() ) { mSchemaName = anUri.username().toUpper(); } QgsDebugMsg( "mSchemaName: '" + mSchemaName + "; mTableName: '" + mTableName ); if ( !anUri.geometryColumn().isEmpty() ) mGeometryColName = anUri.geometryColumn().toUpper(); loadFields(); updateStatistics(); if ( mGeometryColName.isEmpty() ) { // table contains no geometries mWkbType = QgsWkbTypes::NoGeometry; mSRId = 0; } //fill type names into sets mNativeTypes // integer types << QgsVectorDataProvider::NativeType( tr( "8 Bytes integer" ), "bigint", QVariant::Int ) << QgsVectorDataProvider::NativeType( tr( "4 Bytes integer" ), "integer", QVariant::Int ) << QgsVectorDataProvider::NativeType( tr( "2 Bytes integer" ), "smallint", QVariant::Int ) << QgsVectorDataProvider::NativeType( tr( "Decimal number (numeric)" ), "numeric", QVariant::Double, 1, 31, 0, 31 ) << QgsVectorDataProvider::NativeType( tr( "Decimal number (decimal)" ), "decimal", QVariant::Double, 1, 31, 0, 31 ) // floating point << QgsVectorDataProvider::NativeType( tr( "Decimal number (real)" ), "real", QVariant::Double ) << QgsVectorDataProvider::NativeType( tr( "Decimal number (double)" ), "double", QVariant::Double ) // date/time types << QgsVectorDataProvider::NativeType( tr( "Date" ), "date", QVariant::Date, -1, -1, -1, -1 ) << QgsVectorDataProvider::NativeType( tr( "Time" ), "time", QVariant::Time, -1, -1, -1, -1 ) << QgsVectorDataProvider::NativeType( tr( "Date & Time" ), "datetime", QVariant::DateTime, -1, -1, -1, -1 ) // string types << QgsVectorDataProvider::NativeType( tr( "Text, fixed length (char)" ), "char", QVariant::String, 1, 254 ) << QgsVectorDataProvider::NativeType( tr( "Text, variable length (varchar)" ), "varchar", QVariant::String, 1, 32704 ) << QgsVectorDataProvider::NativeType( tr( "Text, variable length large object (clob)" ), "clob", QVariant::String, 1, 2147483647 ) //DBCLOB is for 1073741824 double-byte characters, data length should be the same as CLOB (2147483647)? << QgsVectorDataProvider::NativeType( tr( "Text, variable length large object (dbclob)" ), "dbclob", QVariant::String, 1, 1073741824 ) ; }
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; }