[QGIS Commit] r14435 - in trunk/qgis/src: app providers/spatialite
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Tue Oct 26 04:58:16 EDT 2010
Author: esseffe
Date: 2010-10-26 01:58:16 -0700 (Tue, 26 Oct 2010)
New Revision: 14435
Modified:
trunk/qgis/src/app/qgsspatialitesourceselect.cpp
trunk/qgis/src/app/qgsspatialitesourceselect.h
trunk/qgis/src/providers/spatialite/qgsspatialiteprovider.cpp
trunk/qgis/src/providers/spatialite/qgsspatialiteprovider.h
Log:
a) applied the patch suggested in ticket #3139
b) fixed the SourceSelect dialog so to avoid
showing RasterLite-1 related tables
Modified: trunk/qgis/src/app/qgsspatialitesourceselect.cpp
===================================================================
--- trunk/qgis/src/app/qgsspatialitesourceselect.cpp 2010-10-25 21:01:50 UTC (rev 14434)
+++ trunk/qgis/src/app/qgsspatialitesourceselect.cpp 2010-10-26 08:58:16 UTC (rev 14435)
@@ -507,6 +507,8 @@
{
for ( i = 1; i <= rows; i++ )
{
+ if ( isRasterlite1Datasource( handle, results[( i * columns ) + 0] ) )
+ continue;
QString tableName = QString::fromUtf8( results[( i * columns ) + 0] );
QString column = QString::fromUtf8( results[( i * columns ) + 1] );
QString type = results[( i * columns ) + 2];
@@ -698,6 +700,52 @@
return exists;
}
+bool QgsSpatiaLiteSourceSelect::isRasterlite1Datasource (sqlite3 * handle, const char *table)
+{
+// testing for RasterLite-1 datasources
+ int ret;
+ int i;
+ char **results;
+ int rows;
+ int columns;
+ bool exists = false;
+ int len;
+ char table_raster[4192];
+ char sql[4192];
+
+ strcpy ( table_raster, table );
+ len = strlen( table_raster );
+ if (strlen( table_raster ) < 9)
+ return false;
+ if (strcmp( table_raster + len - 9, "_metadata" ) != 0)
+ return false;
+ // ok, possible candidate
+ strcpy( table_raster + len - 9, "_rasters" );
+
+ // checking if the related "_RASTERS table exists
+ sprintf( sql, "SELECT name FROM sqlite_master WHERE type = 'table' AND name = '%s'", table_raster );
+
+ ret = sqlite3_get_table( handle, sql, &results, &rows, &columns, NULL );
+ if ( ret != SQLITE_OK )
+ return false;
+ if ( rows < 1 )
+ ;
+ else
+ {
+ for ( i = 1; i <= rows; i++ )
+ {
+ if ( results[( i * columns ) + 0] != NULL )
+ {
+ const char *name = results[( i * columns ) + 0];
+ if ( name )
+ exists = true;
+ }
+ }
+ }
+ sqlite3_free_table( results );
+ return exists;
+}
+
bool QgsSpatiaLiteSourceSelect::isDeclaredHidden( sqlite3 * handle, QString table, QString geom )
{
int ret;
Modified: trunk/qgis/src/app/qgsspatialitesourceselect.h
===================================================================
--- trunk/qgis/src/app/qgsspatialitesourceselect.h 2010-10-25 21:01:50 UTC (rev 14434)
+++ trunk/qgis/src/app/qgsspatialitesourceselect.h 2010-10-26 08:58:16 UTC (rev 14435)
@@ -117,6 +117,9 @@
/**Checks if this layer has been declared HIDDEN*/
bool isDeclaredHidden( sqlite3 * handle, QString table, QString geom );
+ /**Checks if this layer is a RasterLite-1 datasource*/
+ bool isRasterlite1Datasource( sqlite3 * handle, const char * table );
+
/**cleaning well-formatted SQL strings*/
QString quotedValue( QString value ) const;
Modified: trunk/qgis/src/providers/spatialite/qgsspatialiteprovider.cpp
===================================================================
--- trunk/qgis/src/providers/spatialite/qgsspatialiteprovider.cpp 2010-10-25 21:01:50 UTC (rev 14434)
+++ trunk/qgis/src/providers/spatialite/qgsspatialiteprovider.cpp 2010-10-26 08:58:16 UTC (rev 14435)
@@ -52,6 +52,8 @@
mGeometryColumn = anUri.geometryColumn();
mSqlitePath = anUri.database();
mSubsetString = anUri.sql();
+ mPrimaryKey = anUri.keyColumn();
+ mQuery = mTableName;
// trying to open the SQLite DB
spatialite_init( 0 );
@@ -131,6 +133,7 @@
{
int ret;
int i;
+ sqlite3_stmt *stmt = NULL;
char **results;
int rows;
int columns;
@@ -138,59 +141,130 @@
QString pkName;
int pkCount = 0;
int fldNo = 0;
+ QString sql;
attributeFields.clear();
- mPrimaryKey.clear();
- QString sql = QString( "PRAGMA table_info(\"%1\")" ).arg( mTableName );
+ if ( !isQuery )
+ {
+ mPrimaryKey.clear();
- ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
- if ( ret != SQLITE_OK )
- goto error;
- if ( rows < 1 )
- ;
- else
- {
- for ( i = 1; i <= rows; i++ )
+ sql = QString( "PRAGMA table_info(%1)" ).arg( quotedIdentifier( mTableName ) );
+
+ ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
+ if ( ret != SQLITE_OK )
+ goto error;
+ if ( rows < 1 )
+ ;
+ else
{
- QString name = QString::fromUtf8( results[( i * columns ) + 1] );
- const char *type = results[( i * columns ) + 2];
- QString pk = results[( i * columns ) + 5];
- if ( pk.toInt() != 0 )
+ for ( i = 1; i <= rows; i++ )
{
- // found a Primary Key column
- pkCount++;
- pkName = name;
- }
-
- if ( name != mGeometryColumn )
- {
- // for sure any SQLite value can be represented as SQLITE_TEXT
- QVariant::Type fieldType = QVariant::String;
-
- // making some assumptions in order to guess a more realistic type
- if ( strcasecmp( type, "int" ) == 0 ||
- strcasecmp( type, "integer" ) == 0 ||
- strcasecmp( type, "bigint" ) == 0 ||
- strcasecmp( type, "smallint" ) == 0 ||
- strcasecmp( type, "tinyint" ) == 0 ||
- strcasecmp( type, "boolean" ) == 0 )
+ QString name = QString::fromUtf8( results[( i * columns ) + 1] );
+ const char *type = results[( i * columns ) + 2];
+ QString pk = results[( i * columns ) + 5];
+ if ( pk.toInt() != 0 )
{
- fieldType = QVariant::Int;
+ // found a Primary Key column
+ pkCount++;
+ pkName = name;
}
- else if ( strcasecmp( type, "real" ) == 0 ||
- strcasecmp( type, "double" ) == 0 ||
- strcasecmp( type, "double precision" ) == 0 || strcasecmp( type, "float" ) == 0 )
+
+ if ( name != mGeometryColumn )
{
- fieldType = QVariant::Double;
+ // for sure any SQLite value can be represented as SQLITE_TEXT
+ QVariant::Type fieldType = QVariant::String;
+
+ // making some assumptions in order to guess a more realistic type
+ if ( strcasecmp( type, "int" ) == 0 ||
+ strcasecmp( type, "integer" ) == 0 ||
+ strcasecmp( type, "bigint" ) == 0 ||
+ strcasecmp( type, "smallint" ) == 0 ||
+ strcasecmp( type, "tinyint" ) == 0 ||
+ strcasecmp( type, "boolean" ) == 0 )
+ {
+ fieldType = QVariant::Int;
+ }
+ else if ( strcasecmp( type, "real" ) == 0 ||
+ strcasecmp( type, "double" ) == 0 ||
+ strcasecmp( type, "double precision" ) == 0 || strcasecmp( type, "float" ) == 0 )
+ {
+ fieldType = QVariant::Double;
+ }
+
+ attributeFields.insert( fldNo++, QgsField( name, fieldType, type, 0, 0, "" ) );
}
-
- attributeFields.insert( fldNo++, QgsField( name, fieldType, type, 0, 0, "" ) );
}
}
+ sqlite3_free_table( results );
}
- sqlite3_free_table( results );
+ else
+ {
+ sql = QString( "select * from %1 limit 1" ).arg( mQuery );
+ 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 ) ) ) );
+ return;
+ }
+
+ ret = sqlite3_step( stmt );
+ if ( ret == SQLITE_DONE )
+ {
+ // there are no rows to fetch
+ sqlite3_finalize( stmt );
+ return;
+ }
+
+ if ( ret == SQLITE_ROW )
+ {
+ // one valid row has been fetched from the result set
+ columns = sqlite3_column_count( stmt );
+ for ( i = 0; i < columns; i++ )
+ {
+ QString name = QString::fromUtf8( sqlite3_column_name( stmt, i ) );
+ const char *type = sqlite3_column_decltype( stmt, i );
+ if ( type == NULL )
+ type = "TEXT";
+
+ if ( name != mPrimaryKey )
+ {
+ pkCount++;
+ pkName = name;
+ }
+
+ if ( name != mGeometryColumn )
+ {
+ // for sure any SQLite value can be represented as SQLITE_TEXT
+ QVariant::Type fieldType = QVariant::String;
+
+ // making some assumptions in order to guess a more realistic type
+ if ( strcasecmp( type, "int" ) == 0 ||
+ strcasecmp( type, "integer" ) == 0 ||
+ strcasecmp( type, "bigint" ) == 0 ||
+ strcasecmp( type, "smallint" ) == 0 ||
+ strcasecmp( type, "tinyint" ) == 0 ||
+ strcasecmp( type, "boolean" ) == 0 )
+ {
+ fieldType = QVariant::Int;
+ }
+ else if ( strcasecmp( type, "real" ) == 0 ||
+ strcasecmp( type, "double" ) == 0 ||
+ strcasecmp( type, "double precision" ) == 0 || strcasecmp( type, "float" ) == 0 )
+ {
+ fieldType = QVariant::Double;
+ }
+
+ attributeFields.insert( fldNo++, QgsField( name, fieldType, type, 0, 0, "" ) );
+ }
+ }
+ }
+ sqlite3_finalize( stmt );
+ }
+
if ( pkCount == 1 )
{
// setting the Primary Key column name
@@ -221,7 +295,9 @@
feature.setValid( false );
- QString sql = "SELECT ROWID";
+ 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 );
@@ -232,7 +308,10 @@
{
sql += QString( ", AsBinary(%1)" ).arg( quotedIdentifier( mGeometryColumn ) );
}
- sql += QString( " FROM %1 WHERE ROWID = %2" ).arg( quotedIdentifier( mTableName ) ).arg( featureId );
+ sql += QString( " FROM %1 WHERE %2 = %3" )
+ .arg( mQuery )
+ .arg( primaryKey )
+ .arg( featureId );
if ( sqlite3_prepare_v2( sqliteHandle, sql.toUtf8().constData(), -1, &stmt, NULL ) != SQLITE_OK )
{
@@ -267,7 +346,7 @@
{
if ( ic == 0 )
{
- // first column always contains the ROWID
+ // first column always contains the ROWID (or the primary key)
feature.setFeatureId( sqlite3_column_int( stmt, ic ) );
}
else
@@ -391,7 +470,7 @@
{
if ( ic == 0 )
{
- // first column always contains the ROWID
+ // first column always contains the ROWID (or the primary key)
feature.setFeatureId( sqlite3_column_int( sqliteStatement, ic ) );
}
else
@@ -522,7 +601,9 @@
sqliteStatement = NULL;
}
- QString sql = "SELECT ROWID";
+ 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 );
@@ -533,7 +614,7 @@
{
sql += QString( ", AsBinary(%1)" ).arg( quotedIdentifier( mGeometryColumn ) );
}
- sql += QString( " FROM %1" ).arg( quotedIdentifier( mTableName ) );
+ sql += QString( " FROM %1" ).arg( mQuery );
QString whereClause;
@@ -569,7 +650,10 @@
mbrFilter += QString( "ymin <= %1 AND " ).arg( QString::number( rect.yMaximum(), 'f', 6 ) );
mbrFilter += QString( "ymax >= %1" ).arg( QString::number( rect.yMinimum(), 'f', 6 ) );
QString idxName = QString( "idx_%1_%2" ).arg( mIndexTable ).arg( mIndexGeometry );
- whereClause += QString( "ROWID IN (SELECT pkid FROM %1 WHERE %2)" ).arg( quotedIdentifier( idxName ) ).arg( mbrFilter );
+ whereClause += QString( "%1 IN (SELECT pkid FROM %2 WHERE %3)" )
+ .arg( quotedIdentifier( primaryKey ) )
+ .arg( quotedIdentifier( idxName ) )
+ .arg( mbrFilter );
}
else if ( spatialIndexMbrCache )
{
@@ -579,7 +663,10 @@
arg( QString::number( rect.yMinimum(), 'f', 6 ) ).
arg( QString::number( rect.xMaximum(), 'f', 6 ) ).arg( QString::number( rect.yMaximum(), 'f', 6 ) );
QString idxName = QString( "cache_%1_%2" ).arg( mIndexTable ).arg( mIndexGeometry );
- whereClause += QString( "ROWID IN (SELECT rowid FROM %1 WHERE mbr = FilterMbrIntersects(%2))" ).arg( quotedIdentifier( idxName ) ).arg( mbr );
+ whereClause += QString( "%1 IN (SELECT rowid FROM %2 WHERE mbr = FilterMbrIntersects(%3))" )
+ .arg( quotedIdentifier( primaryKey ) )
+ .arg( quotedIdentifier( idxName ) )
+ .arg( mbr );
}
else
{
@@ -711,7 +798,7 @@
// get the field name
const QgsField & fld = field( index );
- QString sql = QString( "SELECT Min(\"%1\") FROM \"%2\"" ).arg( fld.name() ).arg( mTableName );
+ QString sql = QString( "SELECT Min(%1) FROM %2" ).arg( quotedIdentifier( fld.name() ) ).arg( mQuery );
if ( !mSubsetString.isEmpty() )
{
@@ -766,7 +853,7 @@
// get the field name
const QgsField & fld = field( index );
- QString sql = QString( "SELECT Max(\"%1\") FROM \"%2\"" ).arg( fld.name() ).arg( mTableName );
+ QString sql = QString( "SELECT Max(%1) FROM %2" ).arg( quotedIdentifier( fld.name() ) ).arg( mQuery );
if ( !mSubsetString.isEmpty() )
{
@@ -819,7 +906,7 @@
// get the field name
const QgsField & fld = field( index );
- sql = QString( "SELECT DISTINCT \"%1\" FROM \"%2\" ORDER BY \"%1\"" ).arg( fld.name() ).arg( mTableName );
+ sql = QString( "SELECT DISTINCT %1 FROM %2 ORDER BY %1" ).arg( quotedIdentifier( fld.name() ) ).arg( mQuery );
if ( !mSubsetString.isEmpty() )
{
@@ -1511,6 +1598,7 @@
mTableBased = false;
mViewBased = false;
mVShapeBased = false;
+ isQuery = false;
// checking if this one is a Table-based layer
QString sql = QString( "SELECT read_only FROM geometry_columns "
@@ -1594,6 +1682,49 @@
}
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;
+ QRegExp regex;
+ do
+ {
+ alias = QString( "subQuery_%1" ).arg( QString::number( index++ ) );
+ QString pattern = QString( "(\\\"?)%1\\1" ).arg( QRegExp::escape( alias ) );
+ regex.setPattern( pattern );
+ regex.setCaseSensitivity( Qt::CaseInsensitive );
+ }
+ while ( mQuery.contains( regex ) );
+
+ // convert the custom query into a subquery
+ mQuery = QString( "%1 as %2" )
+ .arg( mQuery )
+ .arg( quotedIdentifier( alias ) );
+
+ sql = QString( "SELECT 0 FROM %1 LIMIT 1" ).arg( mQuery );
+ ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
+ if ( ret == SQLITE_OK && rows == 1 )
+ {
+ isQuery = 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 );
+ }
+ else
+ {
+ mQuery = quotedIdentifier( mTableName );
+ }
+
// checking for validity
return count == 1;
}
@@ -1607,6 +1738,8 @@
ret = getViewGeometryDetails();
if ( mVShapeBased )
ret = getVShapeGeometryDetails();
+ if ( isQuery )
+ ret = getQueryGeometryDetails();
return ret;
}
@@ -1845,6 +1978,122 @@
return false;
}
+bool QgsSpatiaLiteProvider::getQueryGeometryDetails()
+{
+ int ret;
+ int i;
+ char **results;
+ int rows;
+ int columns;
+ char *errMsg = NULL;
+
+ QString fType( "" );
+ QString xSrid( "" );
+
+ // get stuff from the relevant column instead. This may (will?)
+ // fail if there is no data in the relevant table.
+ QString sql = QString( "select srid(%1), geometrytype(%1) from %2" )
+ .arg( quotedIdentifier( mGeometryColumn ) )
+ .arg( mQuery );
+
+ //it is possible that the where clause restricts the feature type
+ if ( !mSubsetString.isEmpty() )
+ {
+ sql += " WHERE " + mSubsetString;
+ }
+
+ sql += " limit 1";
+
+ ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
+ if ( ret != SQLITE_OK )
+ goto error;
+ if ( rows < 1 )
+ ;
+ else
+ {
+ for ( i = 1; i <= rows; i++ )
+ {
+ xSrid = results[( i * columns ) + 0];
+ fType = results[( i * columns ) + 1];
+ }
+ }
+ sqlite3_free_table( results );
+
+ if ( !xSrid.isEmpty() && !fType.isEmpty() )
+ {
+ if ( fType == "GEOMETRY" )
+ {
+ // check to see if there is a unique geometry type
+ sql = QString( "select distinct "
+ "case"
+ " when geometrytype(%1) IN ('POINT','MULTIPOINT') THEN 'POINT'"
+ " when geometrytype(%1) IN ('LINESTRING','MULTILINESTRING') THEN 'LINESTRING'"
+ " when geometrytype(%1) IN ('POLYGON','MULTIPOLYGON') THEN 'POLYGON'"
+ " end "
+ "from %2" )
+ .arg( quotedIdentifier( mGeometryColumn ) )
+ .arg( mQuery );
+
+ if ( !mSubsetString.isEmpty() )
+ sql += " where " + mSubsetString;
+
+ ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
+ if ( ret != SQLITE_OK )
+ goto error;
+ if ( rows != 1 )
+ ;
+ else
+ {
+ for ( i = 1; i <= rows; i++ )
+ {
+ fType = results[( 1 * columns ) + 0];
+ }
+ }
+ sqlite3_free_table( results );
+ }
+
+ if ( fType == "POINT" )
+ {
+ geomType = QGis::WKBPoint;
+ }
+ else if ( fType == "MULTIPOINT" )
+ {
+ geomType = QGis::WKBMultiPoint;
+ }
+ else if ( fType == "LINESTRING" )
+ {
+ geomType = QGis::WKBLineString;
+ }
+ else if ( fType == "MULTILINESTRING" )
+ {
+ geomType = QGis::WKBMultiLineString;
+ }
+ else if ( fType == "POLYGON" )
+ {
+ geomType = QGis::WKBPolygon;
+ }
+ else if ( fType == "MULTIPOLYGON" )
+ {
+ geomType = QGis::WKBMultiPolygon;
+ }
+ mSrid = xSrid.toInt();
+ }
+
+ if ( geomType == QGis::WKBUnknown || mSrid < 0 )
+ goto error;
+
+ return getSridDetails();
+
+error:
+ // unexpected error
+ if ( errMsg != NULL )
+ {
+ QgsDebugMsg( QString( "SQL error: %1\n\n%2" ).arg( sql ).arg( errMsg ? QString::fromUtf8( errMsg ) : "unknown cause" ) );
+ sqlite3_free( errMsg );
+ }
+ return false;
+}
+
bool QgsSpatiaLiteProvider::getSridDetails()
{
int ret;
@@ -1891,8 +2140,10 @@
int columns;
char *errMsg = NULL;
- QString sql = QString( "SELECT Min(MbrMinX(\"%1\")), Min(MbrMinY(\"%1\")), "
- "Max(MbrMaxX(\"%1\")), Max(MbrMaxY(\"%1\")), Count(*) " "FROM \"%2\"" ).arg( mGeometryColumn ).arg( mTableName );
+ QString sql = QString( "SELECT Min(MbrMinX(%1)), Min(MbrMinY(%1)), "
+ "Max(MbrMaxX(%1)), Max(MbrMaxY(%1)), Count(*) " "FROM %2" )
+ .arg( quotedIdentifier( mGeometryColumn ) )
+ .arg( mQuery );
if ( !mSubsetString.isEmpty() )
{
Modified: trunk/qgis/src/providers/spatialite/qgsspatialiteprovider.h
===================================================================
--- trunk/qgis/src/providers/spatialite/qgsspatialiteprovider.h 2010-10-25 21:01:50 UTC (rev 14434)
+++ trunk/qgis/src/providers/spatialite/qgsspatialiteprovider.h 2010-10-26 08:58:16 UTC (rev 14435)
@@ -257,6 +257,7 @@
void repaintRequested();
private:
+
/** loads fields from input file to member attributeFields */
void loadFields();
@@ -265,6 +266,10 @@
* Flag indicating if the layer data source is a valid SpatiaLite layer
*/
bool valid;
+ /**
+ * Flag indicating if the layer data source is based on a query
+ */
+ bool isQuery;
/**
* Flag indicating if the layer data source is based on a plain Table
*/
@@ -290,6 +295,10 @@
*/
QString mTableName;
/**
+ * Name of the table or subquery
+ */
+ QString mQuery;
+ /**
* Name of the primary key column in the table
*/
QString mPrimaryKey;
@@ -363,6 +372,7 @@
bool getTableGeometryDetails();
bool getViewGeometryDetails();
bool getVShapeGeometryDetails();
+ bool getQueryGeometryDetails();
bool getSridDetails();
bool getTableSummary();
More information about the QGIS-commit
mailing list