mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-04 00:06:46 -05:00
UNIQUE fields detector for sqlite based providers
This is a temporary solution for OGR because we expect to use the native GDAL implementation in GDAL 3.2. For now a new method QgsSqliteUtils::uniqueFields used by spatialite and OGR/GPKG is used to detect UNIQUE constraints on single fields.
This commit is contained in:
parent
bb47d7f745
commit
fa7177a056
@ -52,6 +52,21 @@ Returns a string list of SQLite (and spatialite) system tables
|
||||
|
||||
.. versionadded:: 3.8
|
||||
%End
|
||||
|
||||
static QSet<QString> uniqueFields( sqlite3 *connection, const QString &tableName, QString &errorMessage );
|
||||
%Docstring
|
||||
Returns a list of field names for ``connection`` and ``tableName`` having a UNIQUE constraint,
|
||||
fields that are part of a UNIQUE constraint that spans over multiple fields
|
||||
are not returned.
|
||||
|
||||
.. note::
|
||||
|
||||
the implementation is the same of GDAL but the test coverage is much
|
||||
better in GDAL.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
|
||||
@ -1105,13 +1105,15 @@ void QgsOgrProvider::loadFields()
|
||||
|
||||
// This is a temporary solution until GDAL Unique support is available
|
||||
QSet<QString> uniqueFieldNames;
|
||||
|
||||
|
||||
if ( mGDALDriverName == QLatin1String( "GPKG" ) )
|
||||
{
|
||||
sqlite3_database_unique_ptr dsPtr;
|
||||
if ( dsPtr.open( mFilePath ) == SQLITE_OK )
|
||||
if ( dsPtr.open_v2( mFilePath, SQLITE_OPEN_READONLY, nullptr ) == SQLITE_OK )
|
||||
{
|
||||
QString errMsg;
|
||||
uniqueFieldNames = dsPtr.uniqueFields( mOgrLayer->name(), errMsg );
|
||||
uniqueFieldNames = QgsSqliteUtils::uniqueFields( dsPtr.get(), mOgrLayer->name(), errMsg );
|
||||
if ( ! errMsg.isEmpty() )
|
||||
{
|
||||
QgsMessageLog::logMessage( tr( "GPKG error searching for unique constraints on fields for table %1" ).arg( QString( mOgrLayer->name() ) ), tr( "OGR" ) );
|
||||
|
||||
@ -120,23 +120,23 @@ int sqlite3_database_unique_ptr::exec( const QString &sql, QString &errorMessage
|
||||
return ret;
|
||||
}
|
||||
|
||||
QSet<QString> sqlite3_database_unique_ptr::uniqueFields( const QString &tableName, QString &errorMessage )
|
||||
QSet<QString> QgsSqliteUtils::uniqueFields( sqlite3 *connection, const QString &tableName, QString &errorMessage )
|
||||
{
|
||||
QSet<QString> uniqueFieldsResults;
|
||||
char *zErrMsg = 0;
|
||||
std::vector<std::string> rows;
|
||||
QString sql = sqlite3_mprintf( "select sql from sqlite_master where type='table' and name=%q", QgsSqliteUtils::quotedIdentifier( tableName ).toStdString().c_str() );
|
||||
QString sql = sqlite3_mprintf( "select sql from sqlite_master where type='table' and name=%q", quotedIdentifier( tableName ).toStdString().c_str() );
|
||||
auto cb = [ ](
|
||||
void *data /* Data provided in the 4th argument of sqlite3_exec() */,
|
||||
int /* The number of columns in row */,
|
||||
char **argv /* An array of strings representing fields in the row */,
|
||||
char **/* An array of strings representing column names */ ) -> int
|
||||
char ** /* An array of strings representing column names */ ) -> int
|
||||
{
|
||||
static_cast<std::vector<std::string>*>( data )->push_back( argv[0] );
|
||||
return 0;
|
||||
};
|
||||
|
||||
int rc = sqlite3_exec( get(), sql.toUtf8(), cb, ( void * )&rows, &zErrMsg );
|
||||
int rc = sqlite3_exec( connection, sql.toUtf8(), cb, ( void * )&rows, &zErrMsg );
|
||||
if ( rc != SQLITE_OK )
|
||||
{
|
||||
errorMessage = zErrMsg;
|
||||
@ -172,7 +172,7 @@ QSet<QString> sqlite3_database_unique_ptr::uniqueFields( const QString &tableNam
|
||||
// Search indexes:
|
||||
sql = sqlite3_mprintf( "SELECT sql FROM sqlite_master WHERE type='index' AND"
|
||||
" tbl_name='%q' AND sql LIKE 'CREATE UNIQUE INDEX%%'" );
|
||||
rc = sqlite3_exec( get(), sql.toUtf8(), cb, ( void * )&rows, &zErrMsg );
|
||||
rc = sqlite3_exec( connection, sql.toUtf8(), cb, ( void * )&rows, &zErrMsg );
|
||||
if ( rc != SQLITE_OK )
|
||||
{
|
||||
errorMessage = zErrMsg;
|
||||
|
||||
@ -154,15 +154,6 @@ class CORE_EXPORT sqlite3_database_unique_ptr : public std::unique_ptr< sqlite3,
|
||||
*/
|
||||
int exec( const QString &sql, QString &errorMessage SIP_OUT ) const;
|
||||
|
||||
/**
|
||||
* Returns a list of field names for \a tableName having a UNIQUE constraint,
|
||||
* fields that are part of a UNIQUE constraint that spans over multiple fields
|
||||
* are not returned.
|
||||
* \note the implementation is the same of GDAL but the test coverage is much
|
||||
* better in GDAL.
|
||||
* \since QGIS 3.14
|
||||
*/
|
||||
QSet<QString> uniqueFields( const QString &tableName, QString &errorMessage );
|
||||
};
|
||||
|
||||
/**
|
||||
@ -210,6 +201,17 @@ class CORE_EXPORT QgsSqliteUtils
|
||||
* \since QGIS 3.8
|
||||
*/
|
||||
static QStringList systemTables();
|
||||
|
||||
/**
|
||||
* Returns a list of field names for \a connection and \a tableName having a UNIQUE constraint,
|
||||
* fields that are part of a UNIQUE constraint that spans over multiple fields
|
||||
* are not returned.
|
||||
* \note the implementation is the same of GDAL but the test coverage is much
|
||||
* better in GDAL.
|
||||
* \since QGIS 3.14
|
||||
*/
|
||||
static QSet<QString> uniqueFields( sqlite3 *connection, const QString &tableName, QString &errorMessage );
|
||||
|
||||
};
|
||||
|
||||
#endif // QGSSQLITEUTILS_H
|
||||
|
||||
@ -913,15 +913,11 @@ void QgsSpatiaLiteProvider::fetchConstraints()
|
||||
// Use the same logic implemented in GDAL for GPKG
|
||||
QSet<QString> uniqueFieldNames;
|
||||
{
|
||||
sqlite3_database_unique_ptr dsPtr;
|
||||
if ( dsPtr.open( mSqlitePath ) == SQLITE_OK )
|
||||
QString errMsg;
|
||||
uniqueFieldNames = QgsSqliteUtils::uniqueFields( mSqliteHandle, mTableName, errMsg );
|
||||
if ( ! errMsg.isEmpty() )
|
||||
{
|
||||
QString errMsg;
|
||||
uniqueFieldNames = dsPtr.uniqueFields( mTableName, errMsg );
|
||||
if ( ! errMsg.isEmpty() )
|
||||
{
|
||||
QgsMessageLog::logMessage( tr( "Error searching for unique constraints on fields for table %1" ).arg( mTableName ), tr( "spatialite" ) );
|
||||
}
|
||||
QgsMessageLog::logMessage( tr( "Error searching for unique constraints on fields for table %1" ).arg( mTableName ), tr( "spatialite" ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user