[FEATURE] Improve SpatiaLite provider to manage non-spatial tables

This commit is contained in:
Giuseppe Sucameli 2011-06-30 19:04:59 +02:00
parent 4d051b8b32
commit 890b092238
4 changed files with 283 additions and 279 deletions

View File

@ -91,7 +91,8 @@ QgsSpatiaLiteSourceSelect::QgsSpatiaLiteSourceSelect( QgisApp * app, Qt::WFlags
mSearchModeComboBox->setVisible( false );
mSearchModeLabel->setVisible( false );
mSearchTableEdit->setVisible( false );
cbxAllowGeometrylessTables->setVisible( false );
cbxAllowGeometrylessTables->setDisabled( true );
}
// Slot for performing action when the Add button is clicked
@ -113,6 +114,11 @@ void QgsSpatiaLiteSourceSelect::buildQuery()
setSql( mTablesTreeView->currentIndex() );
}
void QgsSpatiaLiteSourceSelect::on_cbxAllowGeometrylessTables_stateChanged( int )
{
on_btnConnect_clicked();
}
void QgsSpatiaLiteSourceSelect::on_mTablesTreeView_clicked( const QModelIndex &index )
{
mBuildQueryButton->setEnabled( index.parent().isValid() );
@ -269,13 +275,8 @@ sqlite3 *QgsSpatiaLiteSourceSelect::openSpatiaLiteDb( QString path )
if ( gcSpatiaLite && rsSpatiaLite )
return handle;
// this one cannot be a valid SpatiaLite DB - no Spatial MetaData where found
closeSpatiaLiteDb( handle );
errCause = tr( "seems to be a valid SQLite DB, but not a SpatiaLite's one ..." );
QMessageBox::critical( this, tr( "SpatiaLite DB Open Error" ),
tr( "Failure while connecting to: %1\n\n%2" ).arg( mSqlitePath ).arg( errCause ) );
mSqlitePath = "";
return NULL;
// this seems to be a valid SQLite DB, but not a SpatiaLite's one
return handle;
error:
// unexpected IO error
@ -471,6 +472,8 @@ void QgsSpatiaLiteSourceSelect::on_btnConnect_clicked()
{
sqlite3 *handle;
cbxAllowGeometrylessTables->setEnabled( false );
QSettings settings;
QString subKey = cmbConnections->currentText();
int idx = subKey.indexOf( "@" );
@ -517,6 +520,8 @@ void QgsSpatiaLiteSourceSelect::on_btnConnect_clicked()
}
mTablesTreeView->resizeColumnToContents( 0 );
mTablesTreeView->resizeColumnToContents( 1 );
cbxAllowGeometrylessTables->setEnabled( true );
}
QStringList QgsSpatiaLiteSourceSelect::selectedTables()
@ -562,7 +567,7 @@ bool QgsSpatiaLiteSourceSelect::getTableInfo( sqlite3 * handle )
int columns;
char *errMsg = NULL;
bool ok = false;
char sql[1024];
QString sql;
QApplication::setOverrideCursor( Qt::WaitCursor );
// setting the SQLite DB name
@ -571,9 +576,9 @@ bool QgsSpatiaLiteSourceSelect::getTableInfo( sqlite3 * handle )
mTableModel.setSqliteDb( myName );
// the following query return the tables containing a Geometry column
strcpy( sql, "SELECT f_table_name, f_geometry_column, type " );
strcat( sql, "FROM geometry_columns" );
ret = sqlite3_get_table( handle, sql, &results, &rows, &columns, &errMsg );
sql = "SELECT f_table_name, f_geometry_column, type "
"FROM geometry_columns";
ret = sqlite3_get_table( handle, sql.toUtf8(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )
goto error;
if ( rows < 1 )
@ -599,10 +604,10 @@ bool QgsSpatiaLiteSourceSelect::getTableInfo( sqlite3 * handle )
if ( checkViewsGeometryColumns( handle ) )
{
// the following query return the views supporting a Geometry column
strcpy( sql, "SELECT view_name, view_geometry, type " );
strcat( sql, "FROM views_geometry_columns " );
strcat( sql, "JOIN geometry_columns USING (f_table_name, f_geometry_column)" );
ret = sqlite3_get_table( handle, sql, &results, &rows, &columns, &errMsg );
sql = "SELECT view_name, view_geometry, type "
"FROM views_geometry_columns "
"JOIN geometry_columns USING (f_table_name, f_geometry_column)";
ret = sqlite3_get_table( handle, sql.toUtf8(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )
goto error;
if ( rows < 1 )
@ -627,9 +632,9 @@ bool QgsSpatiaLiteSourceSelect::getTableInfo( sqlite3 * handle )
if ( checkVirtsGeometryColumns( handle ) )
{
// the following query return the VirtualShapefiles
strcpy( sql, "SELECT virt_name, virt_geometry, type " );
strcat( sql, "FROM virts_geometry_columns" );
ret = sqlite3_get_table( handle, sql, &results, &rows, &columns, &errMsg );
sql = "SELECT virt_name, virt_geometry, type "
"FROM virts_geometry_columns";
ret = sqlite3_get_table( handle, sql.toUtf8(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )
goto error;
if ( rows < 1 )
@ -651,6 +656,29 @@ bool QgsSpatiaLiteSourceSelect::getTableInfo( sqlite3 * handle )
sqlite3_free_table( results );
}
if ( cbxAllowGeometrylessTables->isChecked() )
{
// get all tables
sql = "SELECT name "
"FROM sqlite_master "
"WHERE type in ('table', 'view')";
ret = sqlite3_get_table( handle, sql.toUtf8(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )
goto error;
if ( rows < 1 )
;
else
{
for ( i = 1; i <= rows; i++ )
{
QString tableName = QString::fromUtf8( results[( i * columns ) + 0] );
mTableModel.addTableEntry( tr( "No geometry" ), tableName, QString::null, "" );
}
ok = true;
}
sqlite3_free_table( results );
}
QApplication::restoreOverrideCursor();
return ok;

View File

@ -85,6 +85,7 @@ class QgsSpatiaLiteSourceSelect: public QDialog, private Ui::QgsDbSourceSelectBa
void on_mSearchTableEdit_textChanged( const QString & text );
void on_mSearchColumnComboBox_currentIndexChanged( const QString & text );
void on_mSearchModeComboBox_currentIndexChanged( const QString & text );
void on_cbxAllowGeometrylessTables_stateChanged( int );
void setSql( const QModelIndex& index );
void on_cmbConnections_activated( int );
void setLayerType( QString table, QString column, QString type );

View File

@ -299,43 +299,74 @@ bool QgsSpatiaLiteProvider::featureAtId( QgsFeatureId featureId, QgsFeature & fe
feature.setValid( false );
QString primaryKey = !isQuery ? "ROWID" : quotedIdentifier( mPrimaryKey );
QString whereClause = QString( "%1=%2" ).arg( primaryKey ).arg( featureId );
QString sql = QString( "SELECT %1" ).arg( primaryKey );
for ( QgsAttributeList::const_iterator it = fetchAttributes.constBegin(); it != fetchAttributes.constEnd(); ++it )
if ( !mSubsetString.isEmpty() )
{
const QgsField & fld = field( *it );
const QString & fieldname = fld.name();
sql += "," + quotedIdentifier( fieldname );
}
if ( fetchGeometry )
{
sql += QString( ", AsBinary(%1)" ).arg( quotedIdentifier( mGeometryColumn ) );
}
sql += QString( " FROM %1 WHERE %2 = %3" )
.arg( mQuery )
.arg( primaryKey )
.arg( featureId );
if ( !whereClause.isEmpty() )
whereClause += " and ";
if ( sqlite3_prepare_v2( sqliteHandle, sql.toUtf8().constData(), -1, &stmt, NULL ) != SQLITE_OK )
whereClause += "(" + mSubsetString + ")";
}
if ( !prepareStatement( stmt, fetchAttributes, fetchGeometry, whereClause ) )
{
// some error occurred
QgsDebugMsg( QString( "SQLite error: %1\n\nSQL: %2" )
.arg( sql )
.arg( QString::fromUtf8( sqlite3_errmsg( sqliteHandle ) ) ) );
return false;
}
if ( !getFeature( stmt, fetchGeometry, feature, fetchAttributes ) )
{
sqlite3_finalize( stmt );
return false;
}
sqlite3_finalize( stmt );
feature.setValid( true );
return true;
}
bool QgsSpatiaLiteProvider::nextFeature( QgsFeature & feature )
{
feature.setValid( false );
if ( !valid )
{
QgsDebugMsg( "Read attempt on an invalid SpatiaLite data source" );
return false;
}
if ( sqliteStatement == NULL )
{
QgsDebugMsg( "Invalid current SQLite statement" );
return false;
}
if ( !getFeature( sqliteStatement, mFetchGeom, feature, mAttributesToFetch ) )
{
sqlite3_finalize( sqliteStatement );
sqliteStatement = NULL;
return false;
}
feature.setValid( true );
return true;
}
bool QgsSpatiaLiteProvider::getFeature( sqlite3_stmt *stmt, bool fetchGeometry,
QgsFeature &feature,
const QgsAttributeList &fetchAttributes)
{
int ret = sqlite3_step( stmt );
if ( ret == SQLITE_DONE )
{
// there are no more rows to fetch - we can stop looping destroying the SQLite statement
sqlite3_finalize( stmt );
// there are no more rows to fetch
return false;
}
if ( ret == SQLITE_ROW )
{
// one valid row has been fetched from the result set
if ( !mFetchGeom )
if ( !fetchGeometry )
{
// no geometry was required
feature.setGeometryAndOwnership( 0, 0 );
@ -350,7 +381,9 @@ bool QgsSpatiaLiteProvider::featureAtId( QgsFeatureId featureId, QgsFeature & fe
if ( ic == 0 )
{
// first column always contains the ROWID (or the primary key)
feature.setFeatureId( sqlite3_column_int( stmt, ic ) );
QgsFeatureId fid = sqlite3_column_int64( stmt, ic );
QgsDebugMsgLevel( QString( "fid=%1" ).arg( fid ), 3 );
feature.setFeatureId( fid );
}
else
{
@ -395,7 +428,7 @@ bool QgsSpatiaLiteProvider::featureAtId( QgsFeatureId featureId, QgsFeature & fe
{
continue;
}
if ( mFetchGeom )
if ( fetchGeometry )
{
QString geoCol = QString( "AsBinary(%1)" ).arg( quotedIdentifier( mGeometryColumn ) );
if ( strcasecmp( geoCol.toUtf8().constData(), sqlite3_column_name( stmt, ic ) ) == 0 )
@ -427,140 +460,9 @@ bool QgsSpatiaLiteProvider::featureAtId( QgsFeatureId featureId, QgsFeature & fe
{
// some unexpected error occurred
QgsDebugMsg( QString( "sqlite3_step() error: %1" ).arg( QString::fromUtf8( sqlite3_errmsg( sqliteHandle ) ) ) );
sqlite3_finalize( stmt );
return false;
}
sqlite3_finalize( stmt );
feature.setValid( true );
return true;
}
bool QgsSpatiaLiteProvider::nextFeature( QgsFeature & feature )
{
feature.setValid( false );
if ( !valid )
{
QgsDebugMsg( "Read attempt on an invalid SpatiaLite data source" );
return false;
}
if ( sqliteStatement == NULL )
{
QgsDebugMsg( "Invalid current SQLite statement" );
return false;
}
int ret = sqlite3_step( sqliteStatement );
if ( ret == SQLITE_DONE )
{
// there are no more rows to fetch - we can stop looping destroying the SQLite statement
sqlite3_finalize( sqliteStatement );
sqliteStatement = NULL;
return false;
}
if ( ret == SQLITE_ROW )
{
// one valid row has been fetched from the result set
if ( !mFetchGeom )
{
// no geometry was required
feature.setGeometryAndOwnership( 0, 0 );
}
feature.clearAttributeMap();
int ic;
int n_columns = sqlite3_column_count( sqliteStatement );
for ( ic = 0; ic < n_columns; ic++ )
{
if ( ic == 0 )
{
// first column always contains the ROWID (or the primary key)
feature.setFeatureId( sqlite3_column_int( sqliteStatement, ic ) );
}
else
{
// iterate attributes
bool fetched = false;
int nAttr = 1;
for ( QgsAttributeList::const_iterator it = mAttributesToFetch.constBegin(); it != mAttributesToFetch.constEnd(); it++ )
{
if ( nAttr == ic )
{
// ok, this one is the corresponding attribure
if ( sqlite3_column_type( sqliteStatement, ic ) == SQLITE_INTEGER )
{
// INTEGER value
feature.addAttribute( *it, sqlite3_column_int( sqliteStatement, ic ) );
fetched = true;
}
else if ( sqlite3_column_type( sqliteStatement, ic ) == SQLITE_FLOAT )
{
// DOUBLE value
feature.addAttribute( *it, sqlite3_column_double( sqliteStatement, ic ) );
fetched = true;
}
else if ( sqlite3_column_type( sqliteStatement, ic ) == SQLITE_TEXT )
{
// TEXT value
const char *txt = ( const char * ) sqlite3_column_text( sqliteStatement, ic );
QString str = QString::fromUtf8( txt );
feature.addAttribute( *it, str );
fetched = true;
}
else
{
// assuming NULL
feature.addAttribute( *it, QVariant( QString::null ) );
fetched = true;
}
}
nAttr++;
}
if ( fetched )
{
continue;
}
if ( mFetchGeom )
{
QString geoCol = QString( "AsBinary(%1)" ).arg( quotedIdentifier( mGeometryColumn ) );
if ( strcasecmp( geoCol.toUtf8().constData(), sqlite3_column_name( sqliteStatement, ic ) ) == 0 )
{
if ( sqlite3_column_type( sqliteStatement, ic ) == SQLITE_BLOB )
{
unsigned char *featureGeom = NULL;
size_t geom_size = 0;
const void *blob = sqlite3_column_blob( sqliteStatement, ic );
size_t blob_size = sqlite3_column_bytes( sqliteStatement, ic );
convertToGeosWKB(( const unsigned char * )blob, blob_size,
&featureGeom, &geom_size );
if ( featureGeom )
feature.setGeometryAndOwnership( featureGeom, geom_size );
else
feature.setGeometryAndOwnership( 0, 0 );
}
else
{
// NULL geometry
feature.setGeometryAndOwnership( 0, 0 );
}
}
}
}
}
}
else
{
// some unexpected error occurred
QgsDebugMsg( QString( "sqlite3_step() error: %1" ).arg( QString::fromUtf8( sqlite3_errmsg( sqliteHandle ) ) ) );
sqlite3_finalize( sqliteStatement );
sqliteStatement = NULL;
return false;
}
feature.setValid( true );
return true;
}
@ -2868,7 +2770,7 @@ bool QgsSpatiaLiteProvider::setSubsetString( QString theSQL, bool updateFeatureC
void QgsSpatiaLiteProvider::select( QgsAttributeList fetchAttributes, QgsRectangle rect, bool fetchGeometry, bool useIntersect )
{
// preparing the SQL statement
QString primaryKey = !isQuery ? "ROWID" : quotedIdentifier( mPrimaryKey );
if ( !valid )
{
@ -2883,27 +2785,11 @@ void QgsSpatiaLiteProvider::select( QgsAttributeList fetchAttributes, QgsRectang
sqliteStatement = NULL;
}
QString primaryKey = !isQuery ? "ROWID" : quotedIdentifier( mPrimaryKey );
QString sql = QString( "SELECT %1" ).arg( primaryKey );
for ( QgsAttributeList::const_iterator it = fetchAttributes.constBegin(); it != fetchAttributes.constEnd(); ++it )
{
const QgsField & fld = field( *it );
const QString & fieldname = fld.name();
sql += "," + quotedIdentifier( fieldname );
}
if ( fetchGeometry )
{
sql += QString( ", AsBinary(%1)" ).arg( quotedIdentifier( mGeometryColumn ) );
}
sql += QString( " FROM %1" ).arg( mQuery );
QString whereClause;
if ( !rect.isEmpty() )
if ( !rect.isEmpty() && !mGeometryColumn.isNull() )
{
// some kind of MBR spatial filtering is required
whereClause = " WHERE ";
if ( useIntersect )
{
// we are requested to evaluate a true INTERSECT relationship
@ -2962,30 +2848,69 @@ void QgsSpatiaLiteProvider::select( QgsAttributeList fetchAttributes, QgsRectang
}
}
if ( !whereClause.isEmpty() )
sql += whereClause;
if ( !mSubsetString.isEmpty() )
{
if ( !whereClause.isEmpty() )
{
sql += " AND ";
whereClause += " AND ";
}
else
{
sql += " WHERE ";
}
sql += "( " + mSubsetString + ")";
whereClause += "( " + mSubsetString + ")";
}
mFetchGeom = fetchGeometry;
mAttributesToFetch = fetchAttributes;
if ( sqlite3_prepare_v2( sqliteHandle, sql.toUtf8().constData(), -1, &sqliteStatement, NULL ) != SQLITE_OK )
// preparing the SQL statement
if ( !prepareStatement( sqliteStatement, fetchAttributes, fetchGeometry, whereClause ) )
{
// some error occurred
sqliteStatement = NULL;
return;
}
}
bool QgsSpatiaLiteProvider::prepareStatement(
sqlite3_stmt *&stmt,
const QgsAttributeList &fetchAttributes,
bool fetchGeometry,
QString whereClause )
{
if ( fetchGeometry && mGeometryColumn.isNull() )
{
return false;
}
QString primaryKey = !isQuery ? "ROWID" : quotedIdentifier( mPrimaryKey );
QString sql = QString( "SELECT %1" ).arg( primaryKey );
for ( QgsAttributeList::const_iterator it = fetchAttributes.constBegin(); it != fetchAttributes.constEnd(); ++it )
{
const QgsField & fld = field( *it );
QString fieldname = quotedIdentifier( fld.name() );
const QString type = fld.typeName().toLower();
if ( type.contains( "geometry" ) || type.contains( "point" ) ||
type.contains( "line" ) || type.contains( "polygon" ) )
{
fieldname = QString( "AsText(%1)" ).arg( fieldname );
}
sql += "," + fieldname;
}
if ( fetchGeometry )
{
sql += QString( ", AsBinary(%1)" ).arg( quotedIdentifier( mGeometryColumn ) );
}
sql += QString( " FROM %1" ).arg( mQuery );
if ( !whereClause.isEmpty() )
sql += QString( " WHERE %1" ).arg( whereClause );
if ( sqlite3_prepare_v2( sqliteHandle, sql.toUtf8().constData(), -1, &stmt, NULL ) != SQLITE_OK )
{
// some error occurred
QgsDebugMsg( QString( "SQLite error: %1\n\nSQL: %2" ).arg( sql ).arg( QString::fromUtf8( sqlite3_errmsg( sqliteHandle ) ) ) );
sqliteStatement = NULL;
return false;
}
return true;
}
@ -3897,92 +3822,44 @@ bool QgsSpatiaLiteProvider::checkLayerType()
mVShapeBased = false;
isQuery = false;
// checking if this one is a Table-based layer
QString sql = QString( "SELECT read_only FROM geometry_columns "
"LEFT JOIN geometry_columns_auth "
"USING (f_table_name, f_geometry_column) "
"WHERE f_table_name=%1 and f_geometry_column=%2" )
.arg( quotedValue( mTableName ) )
.arg( quotedValue( mGeometryColumn ) );
QString sql;
ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )
if ( mGeometryColumn.isNull() )
{
if ( errMsg && strcmp( errMsg, "no such table: geometry_columns_auth" ) == 0 )
// checking if is a non-spatial table
sql = QString( "SELECT type FROM sqlite_master "
"WHERE lower(name) = lower(%1) "
"AND type in ('table', 'view') " ).arg( quotedValue( mTableName ) );
ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret == SQLITE_OK && rows == 1 )
{
sqlite3_free( errMsg );
sql = QString( "SELECT 0 FROM geometry_columns WHERE f_table_name=%1 and f_geometry_column=%2" )
.arg( quotedValue( mTableName ) )
.arg( quotedValue( mGeometryColumn ) );
ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
}
}
if ( ret == SQLITE_OK && rows == 1 )
{
mTableBased = true;
mReadOnly = false;
for ( i = 1; i <= rows; i++ )
{
if ( results[( i * columns ) + 0] != NULL )
QString type = QString( results[( columns ) + 0] );
if ( type == "table" )
{
if ( atoi( results[( i * columns ) + 0] ) != 0 )
mReadOnly = true;
mTableBased = true;
mReadOnly = false;
}
else if ( type == "view" )
{
mViewBased = true;
mReadOnly = true;
}
count++;
}
count++;
if ( errMsg )
{
QgsDebugMsg( QString( "sqlite error %1 [%2]" ).arg( sql ).arg( errMsg ) );
sqlite3_free( errMsg );
errMsg = 0;
}
sqlite3_free_table( results );
}
if ( errMsg )
else if ( mQuery.startsWith( "(select", Qt::CaseInsensitive ) &&
mQuery.endsWith( ")" ) )
{
QgsDebugMsg( QString( "sqlite error %1 [%2]" ).arg( sql ).arg( errMsg ) );
sqlite3_free( errMsg );
errMsg = 0;
}
sqlite3_free_table( results );
// checking if this one is a select query
// checking if this one is a View-based layer
sql = QString( "SELECT view_name, view_geometry FROM views_geometry_columns"
" WHERE view_name=%1 and view_geometry=%2" ).arg( quotedValue( mTableName ) ).
arg( quotedValue( mGeometryColumn ) );
ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret == SQLITE_OK && rows == 1 )
{
mViewBased = true;
mReadOnly = true;
count++;
}
if ( errMsg )
{
QgsDebugMsg( QString( "sqlite error %1 [%2]" ).arg( sql ).arg( errMsg ) );
sqlite3_free( errMsg );
errMsg = 0;
}
sqlite3_free_table( results );
// checking if this one is a VirtualShapefile-based layer
sql = QString( "SELECT virt_name, virt_geometry FROM virts_geometry_columns"
" WHERE virt_name=%1 and virt_geometry=%2" ).arg( quotedValue( mTableName ) ).
arg( quotedValue( mGeometryColumn ) );
ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret == SQLITE_OK && rows == 1 )
{
mVShapeBased = true;
mReadOnly = true;
count++;
}
if ( errMsg )
{
QgsDebugMsg( QString( "sqlite error %1 [%2]" ).arg( sql ).arg( errMsg ) );
sqlite3_free( errMsg );
errMsg = 0;
}
sqlite3_free_table( results );
// checking if this one is a select query
if ( mQuery.startsWith( "(select", Qt::CaseInsensitive ) &&
mQuery.endsWith( ")" ) )
{
// get a new alias for the subquery
int index = 0;
QString alias;
@ -4018,6 +3895,91 @@ bool QgsSpatiaLiteProvider::checkLayerType()
sqlite3_free_table( results );
}
else
{
// checking if this one is a Table-based layer
sql = QString( "SELECT read_only FROM geometry_columns "
"LEFT JOIN geometry_columns_auth "
"USING (f_table_name, f_geometry_column) "
"WHERE f_table_name=%1 and f_geometry_column=%2" )
.arg( quotedValue( mTableName ) )
.arg( quotedValue( mGeometryColumn ) );
ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )
{
if ( errMsg && strcmp( errMsg, "no such table: geometry_columns_auth" ) == 0 )
{
sqlite3_free( errMsg );
sql = QString( "SELECT 0 FROM geometry_columns WHERE f_table_name=%1 and f_geometry_column=%2" )
.arg( quotedValue( mTableName ) )
.arg( quotedValue( mGeometryColumn ) );
ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
}
}
if ( ret == SQLITE_OK && rows == 1 )
{
mTableBased = true;
mReadOnly = false;
for ( i = 1; i <= rows; i++ )
{
if ( results[( i * columns ) + 0] != NULL )
{
if ( atoi( results[( i * columns ) + 0] ) != 0 )
mReadOnly = true;
}
}
count++;
}
if ( errMsg )
{
QgsDebugMsg( QString( "sqlite error %1 [%2]" ).arg( sql ).arg( errMsg ) );
sqlite3_free( errMsg );
errMsg = 0;
}
sqlite3_free_table( results );
// checking if this one is a View-based layer
sql = QString( "SELECT view_name, view_geometry FROM views_geometry_columns"
" WHERE view_name=%1 and view_geometry=%2" ).arg( quotedValue( mTableName ) ).
arg( quotedValue( mGeometryColumn ) );
ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret == SQLITE_OK && rows == 1 )
{
mViewBased = true;
mReadOnly = true;
count++;
}
if ( errMsg )
{
QgsDebugMsg( QString( "sqlite error %1 [%2]" ).arg( sql ).arg( errMsg ) );
sqlite3_free( errMsg );
errMsg = 0;
}
sqlite3_free_table( results );
// checking if this one is a VirtualShapefile-based layer
sql = QString( "SELECT virt_name, virt_geometry FROM virts_geometry_columns"
" WHERE virt_name=%1 and virt_geometry=%2" ).arg( quotedValue( mTableName ) ).
arg( quotedValue( mGeometryColumn ) );
ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret == SQLITE_OK && rows == 1 )
{
mVShapeBased = true;
mReadOnly = true;
count++;
}
if ( errMsg )
{
QgsDebugMsg( QString( "sqlite error %1 [%2]" ).arg( sql ).arg( errMsg ) );
sqlite3_free( errMsg );
errMsg = 0;
}
sqlite3_free_table( results );
}
if ( !isQuery )
{
mQuery = quotedIdentifier( mTableName );
}
@ -4029,6 +3991,12 @@ bool QgsSpatiaLiteProvider::checkLayerType()
bool QgsSpatiaLiteProvider::getGeometryDetails()
{
bool ret = false;
if ( mGeometryColumn.isNull() )
{
geomType = QGis::WKBNoGeometry;
return true;
}
if ( mTableBased )
ret = getTableGeometryDetails();
if ( mViewBased )

View File

@ -380,6 +380,13 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
bool getQueryGeometryDetails();
bool getSridDetails();
bool getTableSummary();
bool prepareStatement( sqlite3_stmt *&stmt,
const QgsAttributeList &fetchAttributes,
bool fetchGeometry,
QString whereClause );
bool getFeature( sqlite3_stmt *stmt, bool fetchGeometry,
QgsFeature &feature,
const QgsAttributeList &fetchAttributes );
void convertToGeosWKB( const unsigned char *blob, size_t blob_size,
unsigned char **wkb, size_t *geom_size );
int computeSizeFromMultiWKB2D( const unsigned char *p_in, int nDims,