QStringList QgsMssqlConnection::schemas( const QString &uri, QString *errorMessage )
{
  QgsDataSourceUri dsUri( uri );

// connect to database
  QSqlDatabase db = getDatabase( dsUri.service(), dsUri.host(), dsUri.database(), dsUri.username(), dsUri.password() );

  if ( !openDatabase( db ) )
  {
    if ( errorMessage )
      *errorMessage = db.lastError().text();
    return QStringList();
  }

  const QString sql = QStringLiteral( "select s.name as schema_name from sys.schemas s" );

  QSqlQuery q = QSqlQuery( db );
  q.setForwardOnly( true );
  if ( !q.exec( sql ) )
  {
    if ( errorMessage )
      *errorMessage = q.lastError().text();
    return QStringList();
  }

  QStringList result;

  while ( q.next() )
  {
    const QString schemaName = q.value( 0 ).toString();
    result << schemaName;
  }
  return result;
}
bool QgsMssqlConnection::createSchema( const QString &uri, const QString &schemaName, QString *errorMessage )
{
  QgsDataSourceUri dsUri( uri );

  // connect to database
  QSqlDatabase db = getDatabase( dsUri.service(), dsUri.host(), dsUri.database(), dsUri.username(), dsUri.password() );

  if ( !openDatabase( db ) )
  {
    if ( errorMessage )
      *errorMessage = db.lastError().text();
    return false;
  }

  QSqlQuery q = QSqlQuery( db );
  q.setForwardOnly( true );
  const QString sql = QStringLiteral( "CREATE SCHEMA [%1]" ).arg( schemaName );
  if ( !q.exec( sql ) )
  {
    if ( errorMessage )
      *errorMessage = q.lastError().text();
    return false;
  }

  return true;
}
bool QgsMssqlConnection::truncateTable( const QString &uri, QString *errorMessage )
{
  QgsDataSourceUri dsUri( uri );

  // connect to database
  QSqlDatabase db = getDatabase( dsUri.service(), dsUri.host(), dsUri.database(), dsUri.username(), dsUri.password() );
  const QString schema = dsUri.schema();
  const QString table = dsUri.table();

  if ( !openDatabase( db ) )
  {
    if ( errorMessage )
      *errorMessage = db.lastError().text();
    return false;
  }

  QSqlQuery q = QSqlQuery( db );
  q.setForwardOnly( true );
  const QString sql = QStringLiteral( "TRUNCATE TABLE [%1].[%2]" ).arg( schema, table );
  if ( !q.exec( sql ) )
  {
    if ( errorMessage )
      *errorMessage = q.lastError().text();
    return false;
  }

  return true;
}
bool QgsMssqlConnection::dropTable( const QString &uri, QString *errorMessage )
{
  QgsDataSourceUri dsUri( uri );

  // connect to database
  QSqlDatabase db = getDatabase( dsUri.service(), dsUri.host(), dsUri.database(), dsUri.username(), dsUri.password() );
  const QString schema = dsUri.schema();
  const QString table = dsUri.table();

  if ( !openDatabase( db ) )
  {
    if ( errorMessage )
      *errorMessage = db.lastError().text();
    return false;
  }

  QSqlQuery q = QSqlQuery( db );
  q.setForwardOnly( true );
  const QString sql = QString( "IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[%1].[%2]') AND type in (N'U')) DROP TABLE [%1].[%2]\n"
                               "DELETE FROM geometry_columns WHERE f_table_schema = '%1' AND f_table_name = '%2'" )
                      .arg( schema,
                            table );
  if ( !q.exec( sql ) )
  {
    if ( errorMessage )
      *errorMessage = q.lastError().text();
    return false;
  }

  return true;
}
Esempio n. 5
0
void QgsProcessingUtils::parseDestinationString( QString &destination, QString &providerKey, QString &uri, QString &layerName, QString &format, QMap<QString, QVariant> &options, bool &useWriter, QString &extension )
{
  extension.clear();
  QRegularExpression splitRx( QStringLiteral( "^(.{3,}?):(.*)$" ) );
  QRegularExpressionMatch match = splitRx.match( destination );
  if ( match.hasMatch() )
  {
    providerKey = match.captured( 1 );
    if ( providerKey == QStringLiteral( "postgis" ) ) // older processing used "postgis" instead of "postgres"
    {
      providerKey = QStringLiteral( "postgres" );
    }
    uri = match.captured( 2 );
    if ( providerKey == QLatin1String( "ogr" ) )
    {
      QgsDataSourceUri dsUri( uri );
      if ( !dsUri.database().isEmpty() )
      {
        if ( !dsUri.table().isEmpty() )
        {
          layerName = dsUri.table();
          options.insert( QStringLiteral( "layerName" ), layerName );
        }
        uri = dsUri.database();
        extension = QFileInfo( uri ).completeSuffix();
        format = QgsVectorFileWriter::driverForExtension( extension );
      }
      else
      {
        extension = QFileInfo( uri ).completeSuffix();
      }
      options.insert( QStringLiteral( "update" ), true );
    }
    useWriter = false;
  }
  else
  {
    useWriter = true;
    providerKey = QStringLiteral( "ogr" );
    QRegularExpression splitRx( QStringLiteral( "^(.*)\\.(.*?)$" ) );
    QRegularExpressionMatch match = splitRx.match( destination );
    if ( match.hasMatch() )
    {
      extension = match.captured( 2 );
      format = QgsVectorFileWriter::driverForExtension( extension );
    }

    if ( format.isEmpty() )
    {
      format = QStringLiteral( "GPKG" );
      destination = destination + QStringLiteral( ".gpkg" );
    }

    options.insert( QStringLiteral( "driverName" ), format );
    uri = destination;
  }
}
Esempio n. 6
0
void QgsPGLayerItem::renameLayer()
{
  QString typeName = mLayerProperty.isView ? tr( "View" ) : tr( "Table" );
  QString lowerTypeName = mLayerProperty.isView ? tr( "view" ) : tr( "table" );

  QgsNewNameDialog dlg( tr( "%1 %2.%3" ).arg( lowerTypeName, mLayerProperty.schemaName, mLayerProperty.tableName ), mLayerProperty.tableName );
  dlg.setWindowTitle( tr( "Rename %1" ).arg( typeName ) );
  if ( dlg.exec() != QDialog::Accepted || dlg.name() == mLayerProperty.tableName )
    return;

  QString schemaName = mLayerProperty.schemaName;
  QString tableName = mLayerProperty.tableName;
  QString schemaTableName;
  if ( !schemaName.isEmpty() )
  {
    schemaTableName = QgsPostgresConn::quotedIdentifier( schemaName ) + '.';
  }
  QString oldName = schemaTableName + QgsPostgresConn::quotedIdentifier( tableName );
  QString newName = QgsPostgresConn::quotedIdentifier( dlg.name() );

  QgsDataSourceUri dsUri( mUri );
  QgsPostgresConn *conn = QgsPostgresConn::connectDb( dsUri.connectionInfo( false ), false );
  if ( !conn )
  {
    QMessageBox::warning( nullptr, tr( "Rename %1" ).arg( typeName ), tr( "Unable to rename %1." ).arg( lowerTypeName ) );
    return;
  }

  //rename the layer
  QString sql;
  if ( mLayerProperty.isView )
  {
    sql = QStringLiteral( "ALTER %1 VIEW %2 RENAME TO %3" ).arg( mLayerProperty.relKind == QLatin1String( "m" ) ? QStringLiteral( "MATERIALIZED" ) : QString(),
          oldName, newName );
  }
  else
  {
    sql = QStringLiteral( "ALTER TABLE %1 RENAME TO %2" ).arg( oldName, newName );
  }

  QgsPostgresResult result( conn->PQexec( sql ) );
  if ( result.PQresultStatus() != PGRES_COMMAND_OK )
  {
    QMessageBox::warning( nullptr, tr( "Rename %1" ).arg( typeName ), tr( "Unable to rename %1 %2\n%3" ).arg( lowerTypeName, mName,
                          result.PQresultErrorMessage() ) );
    conn->unref();
    return;
  }

  conn->unref();
  if ( mParent )
    mParent->refresh();
}
Esempio n. 7
0
void QgsPGLayerItem::refreshMaterializedView()
{
  if ( QMessageBox::question( nullptr, QObject::tr( "Refresh Materialized View" ),
                              QObject::tr( "Are you sure you want to refresh the materialized view %1.%2?\n\nThis will update all data within the table." ).arg( mLayerProperty.schemaName, mLayerProperty.tableName ),
                              QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
    return;

  QgsDataSourceUri dsUri( mUri );
  QgsPostgresConn *conn = QgsPostgresConn::connectDb( dsUri.connectionInfo( false ), false );
  if ( !conn )
  {
    QMessageBox::warning( nullptr, tr( "Refresh View" ), tr( "Unable to refresh the view." ) );
    return;
  }

  QString schemaName = mLayerProperty.schemaName;
  QString tableName = mLayerProperty.tableName;
  QString schemaTableName;
  if ( !schemaName.isEmpty() )
  {
    schemaTableName = QgsPostgresConn::quotedIdentifier( schemaName ) + '.';
  }
  QString tableRef = schemaTableName + QgsPostgresConn::quotedIdentifier( tableName );

  QString sql = QStringLiteral( "REFRESH MATERIALIZED VIEW CONCURRENTLY %1" ).arg( tableRef );

  QgsPostgresResult result( conn->PQexec( sql ) );
  if ( result.PQresultStatus() != PGRES_COMMAND_OK )
  {
    QMessageBox::warning( nullptr, tr( "Refresh View" ), tr( "Unable to refresh view %1\n%2" ).arg( mName,
                          result.PQresultErrorMessage() ) );
    conn->unref();
    return;
  }

  conn->unref();
  QMessageBox::information( nullptr, tr( "Refresh View" ), tr( "Materialized view refreshed successfully." ) );
}
Esempio n. 8
0
void QgsPGLayerItem::truncateTable()
{
  if ( QMessageBox::question( nullptr, QObject::tr( "Truncate Table" ),
                              QObject::tr( "Are you sure you want to truncate %1.%2?\n\nThis will delete all data within the table." ).arg( mLayerProperty.schemaName, mLayerProperty.tableName ),
                              QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
    return;

  QgsDataSourceUri dsUri( mUri );
  QgsPostgresConn *conn = QgsPostgresConn::connectDb( dsUri.connectionInfo( false ), false );
  if ( !conn )
  {
    QMessageBox::warning( nullptr, tr( "Truncate Table" ), tr( "Unable to truncate table." ) );
    return;
  }

  QString schemaName = mLayerProperty.schemaName;
  QString tableName = mLayerProperty.tableName;
  QString schemaTableName;
  if ( !schemaName.isEmpty() )
  {
    schemaTableName = QgsPostgresConn::quotedIdentifier( schemaName ) + '.';
  }
  QString tableRef = schemaTableName + QgsPostgresConn::quotedIdentifier( tableName );

  QString sql = QStringLiteral( "TRUNCATE TABLE %1" ).arg( tableRef );

  QgsPostgresResult result( conn->PQexec( sql ) );
  if ( result.PQresultStatus() != PGRES_COMMAND_OK )
  {
    QMessageBox::warning( nullptr, tr( "Truncate Table" ), tr( "Unable to truncate %1\n%2" ).arg( mName,
                          result.PQresultErrorMessage() ) );
    conn->unref();
    return;
  }

  conn->unref();
  QMessageBox::information( nullptr, tr( "Truncate Table" ), tr( "Table truncated successfully." ) );
}
Esempio n. 9
0
QgsMapLayer* QgsServerProjectParser::createLayerFromElement( const QDomElement& elem, bool useCache ) const
{
  if ( elem.isNull() || !mXMLDoc )
  {
    return nullptr;
  }

  addJoinLayersForElement( elem );
  addGetFeatureLayers( elem );

  QDomElement dataSourceElem = elem.firstChildElement( "datasource" );
  QString uri = dataSourceElem.text();
  QString absoluteUri;
  // If QgsProject instance fileName is set,
  // Is converting relative pathes to absolute still relevant ?
  if ( !dataSourceElem.isNull() )
  {
    //convert relative pathes to absolute ones if necessary
    if ( uri.startsWith( "dbname" ) ) //database
    {
      QgsDataSourceUri dsUri( uri );
      if ( dsUri.host().isEmpty() ) //only convert path for file based databases
      {
        QString dbnameUri = dsUri.database();
        QString dbNameUriAbsolute = convertToAbsolutePath( dbnameUri );
        if ( dbnameUri != dbNameUriAbsolute )
        {
          dsUri.setDatabase( dbNameUriAbsolute );
          absoluteUri = dsUri.uri();
          QDomText absoluteTextNode = mXMLDoc->createTextNode( absoluteUri );
          dataSourceElem.replaceChild( absoluteTextNode, dataSourceElem.firstChild() );
        }
      }
    }
    else if ( uri.startsWith( "file:" ) ) //a file based datasource in url notation (e.g. delimited text layer)
    {
      QString filePath = uri.mid( 5, uri.indexOf( "?" ) - 5 );
      QString absoluteFilePath = convertToAbsolutePath( filePath );
      if ( filePath != absoluteFilePath )
      {
        QUrl destUrl = QUrl::fromEncoded( uri.toAscii() );
        destUrl.setScheme( "file" );
        destUrl.setPath( absoluteFilePath );
        absoluteUri = destUrl.toEncoded();
        QDomText absoluteTextNode = mXMLDoc->createTextNode( absoluteUri );
        dataSourceElem.replaceChild( absoluteTextNode, dataSourceElem.firstChild() );
      }
      else
      {
        absoluteUri = uri;
      }
    }
    else //file based data source
    {
      absoluteUri = convertToAbsolutePath( uri );
      if ( uri != absoluteUri )
      {
        QDomText absoluteTextNode = mXMLDoc->createTextNode( absoluteUri );
        dataSourceElem.replaceChild( absoluteTextNode, dataSourceElem.firstChild() );
      }
    }
  }

  QString id = layerId( elem );
  QgsMapLayer* layer = nullptr;
  if ( useCache )
  {
    layer = QgsMSLayerCache::instance()->searchLayer( absoluteUri, id, mProjectPath );
  }

  if ( layer )
  {
    if ( !QgsMapLayerRegistry::instance()->mapLayer( id ) )
      QgsMapLayerRegistry::instance()->addMapLayer( layer, false, false );
    if ( layer->type() == QgsMapLayer::VectorLayer )
      addValueRelationLayersForLayer( dynamic_cast<QgsVectorLayer *>( layer ) );

    return layer;
  }

  QString type = elem.attribute( "type" );
  if ( type == "vector" )
  {
    layer = new QgsVectorLayer();
  }
  else if ( type == "raster" )
  {
    layer = new QgsRasterLayer();
  }
  else if ( elem.attribute( "embedded" ) == "1" ) //layer is embedded from another project file
  {
    QString project = convertToAbsolutePath( elem.attribute( "project" ) );
    QgsDebugMsg( QString( "Project path: %1" ).arg( project ) );

    QgsServerProjectParser* otherConfig = QgsConfigCache::instance()->serverConfiguration( project );
    if ( !otherConfig )
    {
      return nullptr;
    }
    return otherConfig->mapLayerFromLayerId( elem.attribute( "id" ), useCache );
  }

  if ( layer )
  {
    if ( layer->type() == QgsMapLayer::VectorLayer )
    {
      // see QgsEditorWidgetRegistry::mapLayerAdded()
      QObject::connect( layer, SIGNAL( readCustomSymbology( const QDomElement&, QString& ) ), QgsEditorWidgetRegistry::instance(), SLOT( readSymbology( const QDomElement&, QString& ) ) );
    }

    layer->readLayerXml( const_cast<QDomElement&>( elem ) ); //should be changed to const in QgsMapLayer
    //layer->setLayerName( layerName( elem ) );

    // Insert layer in registry and cache before addValueRelationLayersForLayer
    if ( !QgsMapLayerRegistry::instance()->mapLayer( id ) )
      QgsMapLayerRegistry::instance()->addMapLayer( layer, false, false );
    if ( useCache )
    {
      QgsMSLayerCache::instance()->insertLayer( absoluteUri, id, layer, mProjectPath );
    }
    else
    {
      //todo: fixme
      //mLayersToRemove.push_back( layer );
    }

    if ( layer->type() == QgsMapLayer::VectorLayer )
    {
      addValueRelationLayersForLayer( dynamic_cast<QgsVectorLayer *>( layer ) );
    }
  }
  return layer;
}
Esempio n. 10
0
QgsMapLayer* QgsServerProjectParser::createLayerFromElement( const QDomElement& elem, bool useCache ) const
{
  if ( elem.isNull() || !mXMLDoc )
  {
    return 0;
  }

  addJoinLayersForElement( elem, useCache );
  addValueRelationLayersForElement( elem, useCache );

  QDomElement dataSourceElem = elem.firstChildElement( "datasource" );
  QString uri = dataSourceElem.text();
  QString absoluteUri;
  if ( !dataSourceElem.isNull() )
  {
    //convert relative pathes to absolute ones if necessary
    if ( uri.startsWith( "dbname" ) ) //database
    {
      QgsDataSourceURI dsUri( uri );
      if ( dsUri.host().isEmpty() ) //only convert path for file based databases
      {
        QString dbnameUri = dsUri.database();
        QString dbNameUriAbsolute = convertToAbsolutePath( dbnameUri );
        if ( dbnameUri != dbNameUriAbsolute )
        {
          dsUri.setDatabase( dbNameUriAbsolute );
          absoluteUri = dsUri.uri();
          QDomText absoluteTextNode = mXMLDoc->createTextNode( absoluteUri );
          dataSourceElem.replaceChild( absoluteTextNode, dataSourceElem.firstChild() );
        }
      }
    }
    else if ( uri.startsWith( "file:" ) ) //a file based datasource in url notation (e.g. delimited text layer)
    {
      QString filePath = uri.mid( 5, uri.indexOf( "?" ) - 5 );
      QString absoluteFilePath = convertToAbsolutePath( filePath );
      if ( filePath != absoluteFilePath )
      {
        QUrl destUrl = QUrl::fromEncoded( uri.toAscii() );
        destUrl.setScheme( "file" );
        destUrl.setPath( absoluteFilePath );
        absoluteUri = destUrl.toEncoded();
        QDomText absoluteTextNode = mXMLDoc->createTextNode( absoluteUri );
        dataSourceElem.replaceChild( absoluteTextNode, dataSourceElem.firstChild() );
      }
      else
      {
        absoluteUri = uri;
      }
    }
    else //file based data source
    {
      absoluteUri = convertToAbsolutePath( uri );
      if ( uri != absoluteUri )
      {
        QDomText absoluteTextNode = mXMLDoc->createTextNode( absoluteUri );
        dataSourceElem.replaceChild( absoluteTextNode, dataSourceElem.firstChild() );
      }
    }
  }

  QString id = layerId( elem );
  QgsMapLayer* layer = 0;
  if ( useCache )
  {
    layer = QgsMSLayerCache::instance()->searchLayer( absoluteUri, id );
  }

  if ( layer )
  {
    return layer;
  }

  QString type = elem.attribute( "type" );
  if ( type == "vector" )
  {
    layer = new QgsVectorLayer();
  }
  else if ( type == "raster" )
  {
    layer = new QgsRasterLayer();
  }
  else if ( elem.attribute( "embedded" ) == "1" ) //layer is embedded from another project file
  {
    //todo: fixme
    /*
    QString project = convertToAbsolutePath( elem.attribute( "project" ) );
    QgsDebugMsg( QString( "Project path: %1" ).arg( project ) );

    QgsProjectParser* otherConfig = dynamic_cast<QgsProjectParser*>( QgsConfigCache::instance()->searchConfiguration( project ) );
    if ( !otherConfig )
    {
      return 0;
    }

    QHash< QString, QDomElement >::const_iterator layerIt = otherConfig->mProjectLayerElementsById.find( elem.attribute( "id" ) );
    if ( layerIt == otherConfig->mProjectLayerElementsById.constEnd() )
    {
      return 0;
    }
    return otherConfig->createLayerFromElement( layerIt.value() );
    */
  }

  if ( layer )
  {
    layer->readLayerXML( const_cast<QDomElement&>( elem ) ); //should be changed to const in QgsMapLayer
    layer->setLayerName( layerName( elem ) );
    if ( useCache )
    {
      QgsMSLayerCache::instance()->insertLayer( absoluteUri, id, layer, mProjectPath );
    }
    else
    {
      //todo: fixme
      //mLayersToRemove.push_back( layer );
    }
  }
  return layer;
}
Esempio n. 11
0
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;
}