Skip to content

Commit 302b449

Browse files
committed
[mssql] Add browser actions for deleting and truncating tables
Because we can no longer overwrite tables directly using drag and drop (refs #16805), add some explicit actions which allow dropping existing tables (after user confirmation, of course!)
1 parent 745495f commit 302b449

File tree

4 files changed

+131
-1
lines changed

4 files changed

+131
-1
lines changed

src/providers/mssql/qgsmssqlconnection.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@
1818
#include "qgsmssqlconnection.h"
1919
#include "qgslogger.h"
2020
#include "qgssettings.h"
21+
#include "qgsdatasourceuri.h"
2122
#include <QSqlDatabase>
2223
#include <QThread>
24+
#include <QSqlError>
25+
#include <QSqlQuery>
2326

2427
int QgsMssqlConnection::sConnectionId = 0;
2528

@@ -154,6 +157,67 @@ void QgsMssqlConnection::setInvalidGeometryHandlingDisabled( const QString &name
154157
settings.setValue( "/MSSQL/connections/" + name + "/disableInvalidGeometryHandling", disabled );
155158
}
156159

160+
bool QgsMssqlConnection::dropTable( const QString &uri, QString *errorMessage )
161+
{
162+
QgsDataSourceUri dsUri( uri );
163+
164+
// connect to database
165+
QSqlDatabase db = getDatabase( dsUri.service(), dsUri.host(), dsUri.database(), dsUri.username(), dsUri.password() );
166+
const QString schema = dsUri.schema();
167+
const QString table = dsUri.table();
168+
169+
if ( !openDatabase( db ) )
170+
{
171+
if ( errorMessage )
172+
*errorMessage = db.lastError().text();
173+
return false;
174+
}
175+
176+
QSqlQuery q = QSqlQuery( db );
177+
q.setForwardOnly( true );
178+
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"
179+
"DELETE FROM geometry_columns WHERE f_table_schema = '%1' AND f_table_name = '%2'" )
180+
.arg( schema,
181+
table );
182+
if ( !q.exec( sql ) )
183+
{
184+
if ( errorMessage )
185+
*errorMessage = q.lastError().text();
186+
return false;
187+
}
188+
189+
return true;
190+
}
191+
192+
bool QgsMssqlConnection::truncateTable( const QString &uri, QString *errorMessage )
193+
{
194+
QgsDataSourceUri dsUri( uri );
195+
196+
// connect to database
197+
QSqlDatabase db = getDatabase( dsUri.service(), dsUri.host(), dsUri.database(), dsUri.username(), dsUri.password() );
198+
const QString schema = dsUri.schema();
199+
const QString table = dsUri.table();
200+
201+
if ( !openDatabase( db ) )
202+
{
203+
if ( errorMessage )
204+
*errorMessage = db.lastError().text();
205+
return false;
206+
}
207+
208+
QSqlQuery q = QSqlQuery( db );
209+
q.setForwardOnly( true );
210+
const QString sql = QStringLiteral( "TRUNCATE TABLE [%1].[%2]" ).arg( schema, table );
211+
if ( !q.exec( sql ) )
212+
{
213+
if ( errorMessage )
214+
*errorMessage = q.lastError().text();
215+
return false;
216+
}
217+
218+
return true;
219+
}
220+
157221
QString QgsMssqlConnection::dbConnectionName( const QString &name )
158222
{
159223
// Starting with Qt 5.11, sharing the same connection between threads is not allowed.

src/providers/mssql/qgsmssqlconnection.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,16 @@ class QgsMssqlConnection
118118
*/
119119
static void setInvalidGeometryHandlingDisabled( const QString &name, bool disabled );
120120

121+
/**
122+
* Drops the table referenced by \a uri.
123+
*/
124+
static bool dropTable( const QString &uri, QString *errorMessage );
125+
126+
/**
127+
* Truncates the table referenced by \a uri.
128+
*/
129+
static bool truncateTable( const QString &uri, QString *errorMessage );
130+
121131
private:
122132

123133
/**

src/providers/mssql/qgsmssqldataitems.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,60 @@ QgsMssqlLayerItem::QgsMssqlLayerItem( QgsDataItem *parent, const QString &name,
487487
setState( Populated );
488488
}
489489

490+
QList<QAction *> QgsMssqlLayerItem::actions( QWidget *actionParent )
491+
{
492+
QgsMssqlConnectionItem *connItem = qobject_cast<QgsMssqlConnectionItem *>( parent() ? parent()->parent() : nullptr );
493+
494+
QList<QAction *> lst;
495+
496+
// delete
497+
QAction *actionDeleteLayer = new QAction( tr( "Delete Table" ), actionParent );
498+
connect( actionDeleteLayer, &QAction::triggered, this, [ = ]
499+
{
500+
if ( QMessageBox::question( nullptr, QObject::tr( "Delete Table" ),
501+
QObject::tr( "Are you sure you want to delete [%1].[%2]?" ).arg( mLayerProperty.schemaName, mLayerProperty.tableName ),
502+
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
503+
return;
504+
505+
QString errCause;
506+
bool res = QgsMssqlConnection::dropTable( mUri, &errCause );
507+
if ( !res )
508+
{
509+
QMessageBox::warning( nullptr, tr( "Delete Table" ), errCause );
510+
}
511+
else
512+
{
513+
QMessageBox::information( nullptr, tr( "Delete Table" ), tr( "Table deleted successfully." ) );
514+
if ( connItem )
515+
connItem->refresh();
516+
}
517+
} );
518+
lst.append( actionDeleteLayer );
519+
520+
// truncate
521+
QAction *actionTruncateLayer = new QAction( tr( "Truncate Table" ), actionParent );
522+
connect( actionTruncateLayer, &QAction::triggered, this, [ = ]
523+
{
524+
if ( QMessageBox::question( nullptr, QObject::tr( "Truncate Table" ),
525+
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 ),
526+
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
527+
return;
528+
529+
QString errCause;
530+
bool res = QgsMssqlConnection::truncateTable( mUri, &errCause );
531+
if ( !res )
532+
{
533+
QMessageBox::warning( nullptr, tr( "Truncate Table" ), errCause );
534+
}
535+
else
536+
{
537+
QMessageBox::information( nullptr, tr( "Truncate Table" ), tr( "Table truncated successfully." ) );
538+
}
539+
} );
540+
lst.append( actionTruncateLayer );
541+
return lst;
542+
}
543+
490544
QgsMssqlLayerItem *QgsMssqlLayerItem::createClone()
491545
{
492546
return new QgsMssqlLayerItem( mParent, mName, mPath, mLayerType, mLayerProperty );

src/providers/mssql/qgsmssqldataitems.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,9 @@ class QgsMssqlLayerItem : public QgsLayerItem
126126

127127
public:
128128
QgsMssqlLayerItem( QgsDataItem *parent, const QString &name, const QString &path, QgsLayerItem::LayerType layerType, const QgsMssqlLayerProperty &layerProperties );
129-
129+
#ifdef HAVE_GUI
130+
QList<QAction *> actions( QWidget *parent ) override;
131+
#endif
130132
QString createUri();
131133

132134
QgsMssqlLayerItem *createClone();

0 commit comments

Comments
 (0)