Ticket Hash: | 597fce55f2884668a24b591840162ffebda390e1 | |||
Title: | Adapting addVectorLayerAuth to look for triggers for SpatialViews | |||
Status: | Closed | Type: | Feature_Request | |
Severity: | Important | Priority: | Immediate | |
Subsystem: | Resolution: | Fixed | ||
Last Modified: | 2017-05-30 09:59:19 | |||
Version Found In: | 4.5.0dev | |||
User Comments: | ||||
mj10777 added on 2017-05-12 09:02:06:
Providers have problems in supporting writable SpatialViews properly
QGis does this incorrectly (looks if a trigger exists, but not what type) Since gaiaGetVectorLayersList collects capability information about all Vector Layers, information about what a writable SpatialView is capable of, should be included. typedef struct gaiaLayerAuthInfos after IsReadOnly: /** Flag indicating if the Capabilities of the SpatialView supports Inserting: TRUE or FALSE */ int HasTriggerInsert; /** Flag indicating if the Capabilities of the SpatialView supports Updating: TRUE or FALSE */ int HasTriggerUpdate; /** Flag indicating if the Capabilities of the SpatialView supports Deleting: TRUE or FALSE */ int HasTriggerDelete; addVectorLayerAuth Add 'sqlite3 * handle,' to function parameters, which is called from:
get_table_auth_legacy after setting of IsReadOnly: auth->HasTriggerInsert = 0; auth->HasTriggerUpdate = 0; auth->HasTriggerDelete = 0; if ((lyr->LayerType == GAIA_VECTOR_VIEW) && (!auth->IsReadOnly)) { auth->IsReadOnly = 1; // Claims to be a Writable SpatialView, we shall see ... sql = sqlite3_mprintf("SELECT " "(SELECT Exists(SELECT rootpage FROM sqlite_master WHERE (type = 'trigger' AND Lower(tbl_name) = Lower(%Q) AND (instr(upper(sql),'INSTEAD OF INSERT') > 0)))), " "(SELECT Exists(SELECT rootpage FROM sqlite_master WHERE (type = 'trigger' AND Lower(tbl_name) = Lower(%Q) AND (instr(upper(sql),'INSTEAD OF UPDATE') > 0)))), " "(SELECT Exists(SELECT rootpage FROM sqlite_master WHERE (type = 'trigger' AND Lower(tbl_name) = Lower(%Q) AND (instr(upper(sql),'INSTEAD OF DELETE') > 0))))" , table_name,table_name,table_name); ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL); sqlite3_free (sql); if (ret == SQLITE_OK) { while ( sqlite3_step( stmt ) == SQLITE_ROW ) { if ( sqlite3_column_type( stmt, 0 ) != SQLITE_NULL ) { if ( sqlite3_column_int( stmt, 0 ) == 1 ) { auth->HasTriggerInsert = 1; auth->IsReadOnly = 0; // Yes, this could be a functional Writable SpatialView } } if ( sqlite3_column_type( stmt, 1 ) != SQLITE_NULL ) { if ( sqlite3_column_int( stmt, 1 ) == 1 ) { auth->HasTriggerUpdate = 1; auth->IsReadOnly = 0; // Yes, this could be a functional Writable SpatialView } } if ( sqlite3_column_type( stmt, 2 ) != SQLITE_NULL ) { if ( sqlite3_column_int( stmt, 2 ) == 1 ) { auth->HasTriggerDelete = 1; auth->IsReadOnly = 0; // Yes, this could be a functional Writable SpatialView } } } ret = sqlite3_finalize (stmt); } } Should deal with this matter in a way that Providers could rely upon (As always with no guarantee that the trigger works correctly). sandro added on 2017-05-13 12:07:46: patch accepted and immediately available from the Fossil repo. mj10777 added on 2017-05-13 14:49:32: 2 corrections:
the && should be changed to ||, because if (at least) one is true - then the view is writable. if (*has_trigger_delete && *has_trigger_update && *has_trigger_delete) if (*has_trigger_insert || *has_trigger_update || *has_trigger_delete) sandro added on 2017-05-13 15:41:53: Yes I agree, a View supporting at least one between INSERT, UPDATE or DELETE technically speaking is a Writable View. Anyway this patch is mainly intended to support the QGIS own data provider, and I easily imagine that in this specific context a set of Triggers only implementing an incomplete write support (i.e. INSERT and/or UPDATE but no DELETE) will very probably cause havoc. mj10777 added on 2017-05-13 15:55:38: if readonly is TRUE, no further checking is done. if readonly is FALSE, the 3 settings are checked and the appropriate Capabilities set: if ( mViewBased && !mReadOnly ) { // enabling editing for Spatialview when the corresponding TRIGGER exists if ( mTriggerDelete ) { mEnabledCapabilities |= QgsVectorDataProvider::DeleteFeatures | QgsVectorDataProvider::FastTruncate; } if ( mTriggerUpdate ) { mEnabledCapabilities |= QgsVectorDataProvider::ChangeGeometries; mEnabledCapabilities |= QgsVectorDataProvider::ChangeAttributeValues; } if ( mTriggerInsert ) { mEnabledCapabilities |= QgsVectorDataProvider::AddFeatures; mEnabledCapabilities |= QgsVectorDataProvider::AddAttributes; mEnabledCapabilities |= QgsVectorDataProvider::CreateAttributeIndex; } }In this way, when mTriggerInsert == FALSE, the gui will not allow new geometries to be created
sandro added on 2017-05-14 09:27:03: all right, this definitely clarifies what is the implementation expected by the QGIS data provider. mj10777 added on 2017-05-26 09:18:41: For SpatialViews, addVectorLayerAuth is never called
Legacy: SpatialViews are not contained in geometry_columns_auth Legacy:
gaiaGetVectorLayersList_v4:
API-Documentation should be added for gaiaGetVectorLayersList
sandro added on 2017-05-30 09:59:19: supposed to be fixed by the latest commit. please test if it now correctly works. |