upgraded SpatiaLite provider:

- supporting SpatiaLite 2.4.0 [Release Candidate]
- supporting SQLite 3.6.20 [introducing foreign key constraints]


git-svn-id: http://svn.osgeo.org/qgis/trunk@12163 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
esseffe 2009-11-17 15:59:25 +00:00
parent 06cbfda74b
commit 3e96f7b4d7
13 changed files with 28983 additions and 8421 deletions

View File

@ -39,12 +39,7 @@ QgsSpatiaLiteSourceSelect::QgsSpatiaLiteSourceSelect( QgisApp * app, Qt::WFlags
QDialog( app, fl ), qgisApp( app )
{
setupUi( this );
mAddButton = new QPushButton( tr( "&Add" ) );
buttonBox->addButton( mAddButton, QDialogButtonBox::ActionRole );
connect( mAddButton, SIGNAL( clicked() ), this, SLOT( addClicked() ) );
connect( buttonBox, SIGNAL( helpRequested() ), this, SLOT( helpClicked() ) );
mAddButton->setEnabled( false );
btnAdd->setEnabled( false );
populateConnectionList();
mSearchModeComboBox->addItem( tr( "Wildcard" ) );
@ -84,15 +79,15 @@ void QgsSpatiaLiteSourceSelect::on_btnDelete_clicked()
}
// Slot for performing action when the Add button is clicked
void QgsSpatiaLiteSourceSelect::addClicked()
void QgsSpatiaLiteSourceSelect::on_btnAdd_clicked()
{
addTables();
}
// Slot for showing help
void QgsSpatiaLiteSourceSelect::helpClicked()
void QgsSpatiaLiteSourceSelect::on_btnHelp_clicked()
{
QgsContextHelp::run( context_id );
showHelp();
}
/** End Autoconnected SLOTS **/
@ -480,12 +475,10 @@ void QgsSpatiaLiteSourceSelect::on_btnConnect_clicked()
// BEGIN CHANGES ECOS
if ( cmbConnections->count() > 0 )
mAddButton->setEnabled( true );
btnAdd->setEnabled( true );
// END CHANGES ECOS
mTablesTreeView->sortByColumn( 0, Qt::AscendingOrder );
mTablesTreeView->header()->resizeSection( 1, 140 );
mTablesTreeView->resizeColumnToContents( 0 );
//expand all the toplevel items
int numTopLevelItems = mTableModel.invisibleRootItem()->rowCount();
@ -493,6 +486,8 @@ void QgsSpatiaLiteSourceSelect::on_btnConnect_clicked()
{
mTablesTreeView->expand( mProxyModel.mapFromSource( mTableModel.indexFromItem( mTableModel.invisibleRootItem()->child( i ) ) ) );
}
mTablesTreeView->resizeColumnToContents( 0 );
mTablesTreeView->resizeColumnToContents( 1 );
}
QStringList QgsSpatiaLiteSourceSelect::selectedTables()
@ -514,6 +509,7 @@ bool QgsSpatiaLiteSourceSelect::getTableInfo( sqlite3 * handle )
int columns;
char *errMsg = NULL;
bool ok = false;
char sql[1024];
QApplication::setOverrideCursor( Qt::WaitCursor );
// setting the SQLite DB name
@ -522,8 +518,9 @@ bool QgsSpatiaLiteSourceSelect::getTableInfo( sqlite3 * handle )
mTableModel.setSqliteDb( myName );
// the following query return the tables containing a Geometry column
ret = sqlite3_get_table( handle,
"SELECT f_table_name, f_geometry_column, type FROM geometry_columns", &results, &rows, &columns, &errMsg );
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 );
if ( ret != SQLITE_OK )
goto error;
if ( rows < 1 )
@ -535,6 +532,8 @@ bool QgsSpatiaLiteSourceSelect::getTableInfo( sqlite3 * handle )
QString tableName = results[( i * columns ) + 0];
QString column = results[( i * columns ) + 1];
QString type = results[( i * columns ) + 2];
if ( isDeclaredHidden( handle, tableName, column ))
continue;
mTableModel.addTableEntry( type, tableName, column );
}
@ -542,6 +541,61 @@ bool QgsSpatiaLiteSourceSelect::getTableInfo( sqlite3 * handle )
}
sqlite3_free_table( results );
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 );
if ( ret != SQLITE_OK )
goto error;
if ( rows < 1 )
;
else
{
for ( i = 1; i <= rows; i++ )
{
QString tableName = results[( i * columns ) + 0];
QString column = results[( i * columns ) + 1];
QString type = results[( i * columns ) + 2];
if ( isDeclaredHidden( handle, tableName, column ))
continue;
mTableModel.addTableEntry( type, tableName, column );
}
ok = true;
}
sqlite3_free_table( results );
}
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 );
if ( ret != SQLITE_OK )
goto error;
if ( rows < 1 )
;
else
{
for ( i = 1; i <= rows; i++ )
{
QString tableName = results[( i * columns ) + 0];
QString column = results[( i * columns ) + 1];
QString type = results[( i * columns ) + 2];
if ( isDeclaredHidden( handle, tableName, column ))
continue;
mTableModel.addTableEntry( type, tableName, column );
}
ok = true;
}
sqlite3_free_table( results );
}
QApplication::restoreOverrideCursor();
return ok;
@ -558,6 +612,169 @@ error:
return false;
}
QString QgsSpatiaLiteSourceSelect::quotedValue( QString value ) const
{
if ( value.isNull() )
return "NULL";
value.replace( "'", "''" );
return value.prepend( "'" ).append( "'" );
}
bool QgsSpatiaLiteSourceSelect::checkGeometryColumnsAuth( sqlite3 * handle )
{
int ret;
int i;
char **results;
int rows;
int columns;
bool exists = false;
// checking the metadata tables
QString sql = QString( "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'geometry_columns_auth'" );
ret = sqlite3_get_table( handle, sql.toUtf8().constData(), &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::checkViewsGeometryColumns( sqlite3 * handle )
{
int ret;
int i;
char **results;
int rows;
int columns;
bool exists = false;
// checking the metadata tables
QString sql = QString( "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'views_geometry_columns'" );
ret = sqlite3_get_table( handle, sql.toUtf8().constData(), &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::checkVirtsGeometryColumns( sqlite3 * handle )
{
int ret;
int i;
char **results;
int rows;
int columns;
bool exists = false;
// checking the metadata tables
QString sql = QString( "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'virts_geometry_columns'" );
ret = sqlite3_get_table( handle, sql.toUtf8().constData(), &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;
int i;
char **results;
int rows;
int columns;
char *errMsg = NULL;
bool isHidden = false;
if ( checkGeometryColumnsAuth( handle ) == false )
return false;
// checking if some Layer has been declared as HIDDEN
QString sql = QString( "SELECT hidden FROM geometry_columns_auth"
" WHERE f_table_name=%1 and f_geometry_column=%2" ).arg( quotedValue( table ) ).
arg( quotedValue( geom ) );
ret = sqlite3_get_table( handle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )
goto error;
if ( rows < 1 )
;
else
{
for ( i = 1; i <= rows; i++ )
{
if ( results[( i * columns ) + 0] != NULL)
{
if (atoi( results[( i * columns ) + 0] ) != 0)
isHidden = true;
}
}
}
sqlite3_free_table( results );
return isHidden;
error:
// unexpected IO error
QString errCause = tr( "unknown error cause" );
if ( errMsg != NULL )
{
errCause = errMsg;
sqlite3_free( errMsg );
}
QMessageBox::critical( this, tr( "SpatiaLite getTableInfo Error" ),
tr( "Failure exploring tables from: %1\n\n%2" ).arg( mSqlitePath ).arg( errCause ) );
return false;
}
void QgsSpatiaLiteSourceSelect::showHelp()
{
QgsContextHelp::run( context_id );
}
QString QgsSpatiaLiteSourceSelect::fullDescription( QString table, QString column, QString type )
{
QString full_desc = "";

View File

@ -21,7 +21,6 @@
#include "qgisgui.h"
#include "qgsspatialitefilterproxymodel.h"
#include "qgsspatialitetablemodel.h"
#include <QPushButton>
extern "C"
{
@ -81,14 +80,14 @@ class QgsSpatiaLiteSourceSelect: public QDialog, private Ui::QgsSpatiaLiteSource
* Once connected, available layers are displayed.
*/
void on_btnConnect_clicked();
void addClicked();
void on_btnAdd_clicked();
void on_btnNew_clicked();
void on_btnDelete_clicked();
void on_mSearchOptionsButton_clicked();
void on_mSearchTableEdit_textChanged( const QString & text );
void on_mSearchColumnComboBox_currentIndexChanged( const QString & text );
void on_mSearchModeComboBox_currentIndexChanged( const QString & text );
void helpClicked();
void on_btnHelp_clicked();
void on_cmbConnections_activated( int );
void setLayerType( QString table, QString column, QString type );
//!Sets a new regular expression to the model
@ -106,6 +105,21 @@ class QgsSpatiaLiteSourceSelect: public QDialog, private Ui::QgsSpatiaLiteSource
typedef std::pair < QString, QString > geomPair;
typedef std::list < geomPair > geomCol;
/**Checks if geometry_columns_auth table exists*/
bool checkGeometryColumnsAuth( sqlite3 * handle );
/**Checks if views_geometry_columns table exists*/
bool checkViewsGeometryColumns( sqlite3 * handle );
/**Checks if virts_geometry_columns table exists*/
bool checkVirtsGeometryColumns( sqlite3 * handle );
/**Checks if this layer has been declared HIDDEN*/
bool isDeclaredHidden( sqlite3 * handle, QString table, QString geom );
/**cleaning well-formatted SQL strings*/
QString quotedValue( QString value ) const;
/**Inserts information about the spatial tables into mTableModel*/
bool getTableInfo( sqlite3 * handle );
@ -116,6 +130,8 @@ class QgsSpatiaLiteSourceSelect: public QDialog, private Ui::QgsSpatiaLiteSource
// Set the position of the database connection list to the last
// used one.
void setConnectionListPosition();
// Show the context help for the dialog
void showHelp();
// Combine the table and column data into a single string
// useful for display to the user
QString fullDescription( QString table, QString column, QString type );
@ -131,7 +147,6 @@ class QgsSpatiaLiteSourceSelect: public QDialog, private Ui::QgsSpatiaLiteSource
//! Model that acts as datasource for mTableTreeWidget
QgsSpatiaLiteTableModel mTableModel;
QgsSpatiaLiteFilterProxyModel mProxyModel;
QPushButton * mAddButton;
};
#endif // QGSSPATIALITESOURCESELECT_H

View File

@ -1,7 +1,7 @@
/*
spatialite.h -- Gaia spatial support for SQLite
version 2.3, 2008 October 13
version 2.4, 2009 September 17
Author: Sandro Furieri a.furieri@lqt.it

View File

@ -1,7 +1,7 @@
/*
gaiaaux.h -- Gaia common utility functions
version 2.3, 2008 October 13
version 2.4, 2009 September 17
Author: Sandro Furieri a.furieri@lqt.it

View File

@ -1,7 +1,7 @@
/*
gaiaexif.h -- Gaia common EXIF Metadata reading functions
version 2.3, 2008 October 13
version 2.4, 2009 September 17
Author: Sandro Furieri a.furieri@lqt.it

View File

@ -1,7 +1,7 @@
/*
gaiageo.h -- Gaia common support for geometries
version 2.3, 2008 October 13
version 2.4, 2009 September 17
Author: Sandro Furieri a.furieri@lqt.it
@ -77,14 +77,45 @@ extern "C"
#define GAIA_MARK_ENTITY 0x69
/* constants that defines GEOMETRY CLASSes */
#define GAIA_UNKNOWN 0
#define GAIA_POINT 1
#define GAIA_LINESTRING 2
#define GAIA_POLYGON 3
#define GAIA_MULTIPOINT 4
#define GAIA_MULTILINESTRING 5
#define GAIA_MULTIPOLYGON 6
#define GAIA_GEOMETRYCOLLECTION 7
#define GAIA_UNKNOWN 0
#define GAIA_POINT 1
#define GAIA_LINESTRING 2
#define GAIA_POLYGON 3
#define GAIA_MULTIPOINT 4
#define GAIA_MULTILINESTRING 5
#define GAIA_MULTIPOLYGON 6
#define GAIA_GEOMETRYCOLLECTION 7
#define GAIA_POINTZ 1001
#define GAIA_LINESTRINGZ 1002
#define GAIA_POLYGONZ 1003
#define GAIA_MULTIPOINTZ 1004
#define GAIA_MULTILINESTRINGZ 1005
#define GAIA_MULTIPOLYGONZ 1006
#define GAIA_GEOMETRYCOLLECTIONZ 1007
#define GAIA_POINTM 2001
#define GAIA_LINESTRINGM 2002
#define GAIA_POLYGONM 2003
#define GAIA_MULTIPOINTM 2004
#define GAIA_MULTILINESTRINGM 2005
#define GAIA_MULTIPOLYGONM 2006
#define GAIA_GEOMETRYCOLLECTIONM 2007
#define GAIA_POINTZM 3001
#define GAIA_LINESTRINGZM 3002
#define GAIA_POLYGONZM 3003
#define GAIA_MULTIPOINTZM 3004
#define GAIA_MULTILINESTRINGZM 3005
#define GAIA_MULTIPOLYGONZM 3006
#define GAIA_GEOMETRYCOLLECTIONZM 3007
/* constants that defines Compressed GEOMETRY CLASSes */
#define GAIA_COMPRESSED_LINESTRING 1000002
#define GAIA_COMPRESSED_POLYGON 1000003
#define GAIA_COMPRESSED_LINESTRINGZ 1001002
#define GAIA_COMPRESSED_POLYGONZ 1001003
#define GAIA_COMPRESSED_LINESTRINGM 1002002
#define GAIA_COMPRESSED_POLYGONM 1002003
#define GAIA_COMPRESSED_LINESTRINGZM 1003002
#define GAIA_COMPRESSED_POLYGONZM 1003003
/* constants that defines token codes for WKT parsing */
#define GAIA_COORDINATE 8
@ -114,29 +145,31 @@ extern "C"
#define GAIA_MBR_WITHIN 7
/* constants used for FilterMBR */
#define GAIA_FILTER_MBR_WITHIN 74
#define GAIA_FILTER_MBR_CONTAINS 77
#define GAIA_FILTER_MBR_INTERSECTS 79
#define GAIA_FILTER_MBR_DECLARE 89
#define GAIA_FILTER_MBR_WITHIN 74
#define GAIA_FILTER_MBR_CONTAINS 77
#define GAIA_FILTER_MBR_INTERSECTS 79
#define GAIA_FILTER_MBR_DECLARE 89
/* constants defining SVG default values */
#define GAIA_SVG_DEFAULT_RELATIVE 0
#define GAIA_SVG_DEFAULT_PRECISION 6
#define GAIA_SVG_DEFAULT_RELATIVE 0
#define GAIA_SVG_DEFAULT_PRECISION 6
#define GAIA_SVG_DEFAULT_MAX_PRECISION 15
/* constants used for VirtualNetwork */
#define GAIA_NET_START 0x67
#define GAIA_NET_END 0x87
#define GAIA_NET_HEADER 0xc0
#define GAIA_NET_CODE 0xa6
#define GAIA_NET_START 0x67
#define GAIA_NET64_START 0x68
#define GAIA_NET_END 0x87
#define GAIA_NET_HEADER 0xc0
#define GAIA_NET_CODE 0xa6
#define GAIA_NET_ID 0xb5
#define GAIA_NET_NODE 0xde
#define GAIA_NET_ARC 0x54
#define GAIA_NET_TABLE 0xa0
#define GAIA_NET_FROM 0xa1
#define GAIA_NET_NODE 0xde
#define GAIA_NET_ARC 0x54
#define GAIA_NET_TABLE 0xa0
#define GAIA_NET_FROM 0xa1
#define GAIA_NET_TO 0xa2
#define GAIA_NET_GEOM 0xa3
#define GAIA_NET_BLOCK 0xed
#define GAIA_NET_GEOM 0xa3
#define GAIA_NET_NAME 0xa4
#define GAIA_NET_BLOCK 0xed
/* constants used for Coordinate Dimensions */
#define GAIA_XY 0x00
@ -144,18 +177,95 @@ extern "C"
#define GAIA_XY_M 0x02
#define GAIA_XY_Z_M 0x03
/* constants used for length unit conversion */
#define GAIA_KM 0
#define GAIA_M 1
#define GAIA_DM 2
#define GAIA_CM 3
#define GAIA_MM 4
#define GAIA_KMI 5
#define GAIA_IN 6
#define GAIA_FT 7
#define GAIA_YD 8
#define GAIA_MI 9
#define GAIA_FATH 10
#define GAIA_CH 11
#define GAIA_LINK 12
#define GAIA_US_IN 13
#define GAIA_US_FT 14
#define GAIA_US_YD 15
#define GAIA_US_CH 16
#define GAIA_US_MI 17
#define GAIA_IND_YD 18
#define GAIA_IND_FT 19
#define GAIA_IND_CH 20
#define GAIA_MIN_UNIT GAIA_KM
#define GAIA_MAX_UNIT GAIA_IND_CH
/* constants used for SHAPES */
#define GAIA_SHP_NULL 0
#define GAIA_SHP_POINT 1
#define GAIA_SHP_POLYLINE 3
#define GAIA_SHP_POLYGON 5
#define GAIA_SHP_MULTIPOINT 8
#define GAIA_SHP_POINTZ 11
#define GAIA_SHP_POLYLINEZ 13
#define GAIA_SHP_POLYGONZ 15
#define GAIA_SHP_MULTIPOINTZ 18
#define GAIA_SHP_POINTM 21
#define GAIA_SHP_POLYLINEM 23
#define GAIA_SHP_POLYGONM 25
#define GAIA_SHP_MULTIPOINTM 28
/* macros */
#define gaiaGetPoint(xy,v,x,y) {*x = xy[(v) * 2]; \
#define gaiaGetPoint(xy,v,x,y) \
{*x = xy[(v) * 2]; \
*y = xy[(v) * 2 + 1];}
#define gaiaSetPoint(xy,v,x,y) {xy[(v) * 2] = x; \
#define gaiaSetPoint(xy,v,x,y) \
{xy[(v) * 2] = x; \
xy[(v) * 2 + 1] = y;}
#define gaiaGetPointXYZ(xyz,v,x,y,z) \
{*x = xyz[(v) * 3]; \
*y = xyz[(v) * 3 + 1]; \
*z = xyz[(v) * 3 + 2];}
#define gaiaSetPointXYZ(xyz,v,x,y,z) \
{xyz[(v) * 3] = x; \
xyz[(v) * 3 + 1] = y; \
xyz[(v) * 3 + 2] = z;}
#define gaiaGetPointXYM(xym,v,x,y,m) \
{*x = xym[(v) * 3]; \
*y = xym[(v) * 3 + 1]; \
*m = xym[(v) * 3 + 2];}
#define gaiaSetPointXYM(xym,v,x,y,m) \
{xym[(v) * 3] = x; \
xym[(v) * 3 + 1] = y; \
xym[(v) * 3 + 2] = m;}
#define gaiaGetPointXYZM(xyzm,v,x,y,z,m) \
{*x = xyzm[(v) * 4]; \
*y = xyzm[(v) * 4 + 1]; \
*z = xyzm[(v) * 4 + 2]; \
*m = xyzm[(v) * 4 + 3];}
#define gaiaSetPointXYZM(xyzm,v,x,y,z,m) \
{xyzm[(v) * 4] = x; \
xyzm[(v) * 4 + 1] = y; \
xyzm[(v) * 4 + 2] = z; \
xyzm[(v) * 4 + 3] = m;}
typedef struct gaiaPointStruct
{
/* an OpenGis POINT */
double X; /* X,Y coordinates */
double Y;
double Z; /* Z coordinate */
double M; /* M measure */
int DimensionModel; /* (x,y), (x,y,z), (x,y,m) or (x,y,z,m) */
struct gaiaPointStruct *Next; /* for double-linked list */
struct gaiaPointStruct *Prev; /* for double-linked list */
} gaiaPoint;
@ -178,6 +288,7 @@ extern "C"
double MinY; /* MBR - BBOX */
double MaxX; /* MBR - BBOX */
double MaxY; /* MBR - BBOX */
int DimensionModel; /* (x,y), (x,y,z), (x,y,m) or (x,y,z,m) */
struct gaiaLinestringStruct *Next; /* for linked list */
} gaiaLinestring;
typedef gaiaLinestring *gaiaLinestringPtr;
@ -192,6 +303,7 @@ extern "C"
double MinY; /* MBR - BBOX */
double MaxX; /* MBR - BBOX */
double MaxY; /* MBR - BBOX */
int DimensionModel; /* (x,y), (x,y,z), (x,y,m) or (x,y,z,m) */
struct gaiaRingStruct *Next; /* for linked list */
struct gaiaPolygonStruct *Link; /* polygon reference */
} gaiaRing;
@ -208,6 +320,7 @@ extern "C"
double MinY; /* MBR - BBOX */
double MaxX; /* MBR - BBOX */
double MaxY; /* MBR - BBOX */
int DimensionModel; /* (x,y), (x,y,z), (x,y,m) or (x,y,z,m) */
struct gaiaPolygonStruct *Next; /* for linked list */
} gaiaPolygon;
typedef gaiaPolygon *gaiaPolygonPtr;
@ -231,6 +344,7 @@ extern "C"
double MinY; /* MBR - BBOX */
double MaxX; /* MBR - BBOX */
double MaxY; /* MBR - BBOX */
int DimensionModel; /* (x,y), (x,y,z), (x,y,m) or (x,y,z,m) */
int DeclaredType; /* the declared TYPE for this Geometry */
} gaiaGeomColl;
typedef gaiaGeomColl *gaiaGeomCollPtr;
@ -304,7 +418,8 @@ extern "C"
double MaxY;
void *IconvObj; /* opaque reference to ICONV converter */
char *LastError; /* last error message */
unsigned char EffectiveType; /* the effective Geometry-type, as determined by gaiaShpAnalyze() */
int EffectiveType; /* the effective Geometry-type, as determined by gaiaShpAnalyze() */
int EffectiveDims; /* the effective Dimensions [XY, XYZ, XYM, XYZM], as determined by gaiaShpAnalyze() */
} gaiaShapefile;
typedef gaiaShapefile *gaiaShapefilePtr;
@ -316,35 +431,91 @@ extern "C"
int little_endian_arch);
GAIAGEO_DECLARE int gaiaImport32 (const unsigned char *p, int little_endian,
int little_endian_arch);
GAIAGEO_DECLARE float gaiaImportF32 (const unsigned char *p,
int little_endian,
int little_endian_arch);
GAIAGEO_DECLARE double gaiaImport64 (const unsigned char *p,
int little_endian,
int little_endian_arch);
GAIAGEO_DECLARE sqlite3_int64 gaiaImportI64 (const unsigned char *p,
int little_endian,
int little_endian_arch);
GAIAGEO_DECLARE void gaiaExport16 (unsigned char *p, short value,
int little_endian,
int little_endian_arch);
GAIAGEO_DECLARE void gaiaExport32 (unsigned char *p, int value,
int little_endian,
int little_endian_arch);
GAIAGEO_DECLARE void gaiaExportF32 (unsigned char *p, float value,
int little_endian,
int little_endian_arch);
GAIAGEO_DECLARE void gaiaExport64 (unsigned char *p, double value,
int little_endian,
int little_endian_arch);
GAIAGEO_DECLARE void gaiaExportI64 (unsigned char *p, sqlite3_int64 value,
int little_endian,
int little_endian_arch);
GAIAGEO_DECLARE gaiaPointPtr gaiaAllocPoint (double x, double y);
GAIAGEO_DECLARE gaiaPointPtr gaiaAllocPointXYZ (double x, double y,
double z);
GAIAGEO_DECLARE gaiaPointPtr gaiaAllocPointXYM (double x, double y,
double m);
GAIAGEO_DECLARE gaiaPointPtr gaiaAllocPointXYZM (double x, double y,
double z, double m);
GAIAGEO_DECLARE void gaiaFreePoint (gaiaPointPtr ptr);
GAIAGEO_DECLARE gaiaLinestringPtr gaiaAllocLinestring (int vert);
GAIAGEO_DECLARE gaiaLinestringPtr gaiaAllocLinestringXYZ (int vert);
GAIAGEO_DECLARE gaiaLinestringPtr gaiaAllocLinestringXYM (int vert);
GAIAGEO_DECLARE gaiaLinestringPtr gaiaAllocLinestringXYZM (int vert);
GAIAGEO_DECLARE void gaiaFreeLinestring (gaiaLinestringPtr ptr);
GAIAGEO_DECLARE void gaiaCopyLinestringCoords (gaiaLinestringPtr dst,
gaiaLinestringPtr src);
GAIAGEO_DECLARE gaiaRingPtr gaiaAllocRing (int vert);
GAIAGEO_DECLARE gaiaRingPtr gaiaAllocRingXYZ (int vert);
GAIAGEO_DECLARE gaiaRingPtr gaiaAllocRingXYM (int vert);
GAIAGEO_DECLARE gaiaRingPtr gaiaAllocRingXYZM (int vert);
GAIAGEO_DECLARE void gaiaFreeRing (gaiaRingPtr ptr);
GAIAGEO_DECLARE void gaiaCopyRingCoords (gaiaRingPtr dst, gaiaRingPtr src);
GAIAGEO_DECLARE gaiaPolygonPtr gaiaAllocPolygon (int vert, int excl);
GAIAGEO_DECLARE gaiaPolygonPtr gaiaAllocPolygonXYZ (int vert, int excl);
GAIAGEO_DECLARE gaiaPolygonPtr gaiaAllocPolygonXYM (int vert, int excl);
GAIAGEO_DECLARE gaiaPolygonPtr gaiaAllocPolygonXYZM (int vert, int excl);
GAIAGEO_DECLARE gaiaPolygonPtr gaiaCreatePolygon (gaiaRingPtr ring);
GAIAGEO_DECLARE void gaiaFreePolygon (gaiaPolygonPtr p);
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaAllocGeomColl (void);
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaAllocGeomCollXYZ (void);
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaAllocGeomCollXYM (void);
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaAllocGeomCollXYZM (void);
GAIAGEO_DECLARE void gaiaFreeGeomColl (gaiaGeomCollPtr p);
GAIAGEO_DECLARE void gaiaAddPointToGeomColl (gaiaGeomCollPtr p, double x,
double y);
GAIAGEO_DECLARE void gaiaAddPointToGeomCollXYZ (gaiaGeomCollPtr p, double x,
double y, double z);
GAIAGEO_DECLARE void gaiaAddPointToGeomCollXYM (gaiaGeomCollPtr p, double x,
double y, double m);
GAIAGEO_DECLARE void gaiaAddPointToGeomCollXYZM (gaiaGeomCollPtr p,
double x, double y,
double z, double m);
GAIAGEO_DECLARE void gaiaMbrLinestring (gaiaLinestringPtr line);
GAIAGEO_DECLARE void gaiaMbrRing (gaiaRingPtr rng);
GAIAGEO_DECLARE void gaiaMbrPolygon (gaiaPolygonPtr polyg);
GAIAGEO_DECLARE void gaiaMbrGeometry (gaiaGeomCollPtr geom);
GAIAGEO_DECLARE void gaiaZRangeLinestring (gaiaLinestringPtr line,
double *min, double *max);
GAIAGEO_DECLARE void gaiaZRangeRing (gaiaRingPtr rng, double *min,
double *max);
GAIAGEO_DECLARE void gaiaZRangePolygon (gaiaPolygonPtr polyg, double *min,
double *max);
GAIAGEO_DECLARE void gaiaZRangeGeometry (gaiaGeomCollPtr geom, double *min,
double *max);
GAIAGEO_DECLARE void gaiaMRangeLinestring (gaiaLinestringPtr line,
double *min, double *max);
GAIAGEO_DECLARE void gaiaMRangeRing (gaiaRingPtr rng, double *min,
double *max);
GAIAGEO_DECLARE void gaiaMRangePolygon (gaiaPolygonPtr polyg, double *min,
double *max);
GAIAGEO_DECLARE void gaiaMRangeGeometry (gaiaGeomCollPtr geom, double *min,
double *max);
GAIAGEO_DECLARE gaiaLinestringPtr
gaiaAddLinestringToGeomColl (gaiaGeomCollPtr p, int vert);
GAIAGEO_DECLARE void gaiaInsertLinestringInGeomColl (gaiaGeomCollPtr p,
@ -402,7 +573,8 @@ extern "C"
int pos);
GAIAGEO_DECLARE gaiaDynamicLinePtr gaiaCreateDynamicLine (double *coords,
int points);
GAIAGEO_DECLARE double gaiaMeasureLength (double *coords, int vert);
GAIAGEO_DECLARE double gaiaMeasureLength (int dims, double *coords,
int vert);
GAIAGEO_DECLARE double gaiaMeasureArea (gaiaRingPtr ring);
GAIAGEO_DECLARE void gaiaRingCentroid (gaiaRingPtr ring, double *rx,
double *ry);
@ -410,7 +582,8 @@ extern "C"
GAIAGEO_DECLARE int gaiaIsPointOnRingSurface (gaiaRingPtr ring, double pt_x,
double pt_y);
GAIAGEO_DECLARE double gaiaMinDistance (double x0, double y0,
double *coords, int n_vert);
int dims, double *coords,
int n_vert);
GAIAGEO_DECLARE int gaiaIsPointOnPolygonSurface (gaiaPolygonPtr polyg,
double x, double y);
GAIAGEO_DECLARE int gaiaIntersect (double *x0, double *y0, double x1,
@ -424,6 +597,9 @@ extern "C"
GAIAGEO_DECLARE void gaiaToSpatiaLiteBlobWkb (gaiaGeomCollPtr geom,
unsigned char **result,
int *size);
GAIAGEO_DECLARE void gaiaToCompressedBlobWkb (gaiaGeomCollPtr geom,
unsigned char **result,
int *size);
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaFromSpatiaLiteBlobMbr (const unsigned
char *blob,
unsigned int
@ -519,6 +695,13 @@ extern "C"
GAIAGEO_DECLARE void gaiaReflectCoords (gaiaGeomCollPtr geom, int x_axis,
int y_axis);
GAIAGEO_DECLARE void gaiaSwapCoords (gaiaGeomCollPtr geom);
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaCastGeomCollToXY (gaiaGeomCollPtr geom);
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaCastGeomCollToXYZ (gaiaGeomCollPtr
geom);
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaCastGeomCollToXYM (gaiaGeomCollPtr
geom);
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaCastGeomCollToXYZM (gaiaGeomCollPtr
geom);
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaCloneGeomColl (gaiaGeomCollPtr geom);
GAIAGEO_DECLARE gaiaLinestringPtr gaiaCloneLinestring (gaiaLinestringPtr
line);
@ -552,6 +735,23 @@ extern "C"
GAIAGEO_DECLARE int gaiaGetMbrMaxY (const unsigned char *blob,
unsigned int size, double *maxy);
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaBuildRings (gaiaGeomCollPtr geom);
GAIAGEO_DECLARE void gaiaFree (void *ptr);
GAIAGEO_DECLARE int gaiaEllipseParams (const char *name, double *a,
double *b, double *rf);
GAIAGEO_DECLARE double gaiaGreatCircleDistance (double a, double b,
double lat1, double lon1,
double lat2, double lon2);
GAIAGEO_DECLARE double gaiaGeodesicDistance (double a, double b, double rf,
double lat1, double lon1,
double lat2, double lon2);
GAIAGEO_DECLARE double gaiaGreatCircleTotalLength (double a, double b,
int dims, double *coords,
int vert);
GAIAGEO_DECLARE double gaiaGeodesicTotalLength (double a, double b,
double rf, int dims,
double *coords, int vert);
GAIAGEO_DECLARE int gaiaConvertLength (double value, int unit_from,
int unit_to, double *cvt);
#ifndef OMIT_PROJ /* including PROJ.4 */
@ -624,6 +824,11 @@ extern "C"
int points);
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaPolygonize (gaiaGeomCollPtr geom,
int force_multipolygon);
GAIAGEO_DECLARE void *gaiaToGeos (const gaiaGeomCollPtr gaia);
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaFromGeos_XY (const void *geos);
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaFromGeos_XYZ (const void *geos);
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaFromGeos_XYM (const void *geos);
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaFromGeos_XYZM (const void *geos);
#endif /* end including GEOS */

View File

@ -1,7 +1,7 @@
/*
spatialite.h -- Gaia support for SQLite extensions
version 2.3, 2008 October 13
version 2.4, 2009 September 17
Author: Sandro Furieri a.furieri@lqt.it

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -48,7 +48,7 @@ QgsSpatiaLiteProvider::QgsSpatiaLiteProvider( QString const &uri ): QgsVectorDat
// parsing members from the uri structure
mTableName = anUri.table();
geometryColumn = anUri.geometryColumn();
mGeometryColumn = anUri.geometryColumn();
mSqlitePath = anUri.database();
mSubsetString = anUri.sql();
@ -63,12 +63,26 @@ QgsSpatiaLiteProvider::QgsSpatiaLiteProvider( QString const &uri ): QgsVectorDat
}
sqliteHandle = handle->handle();
if ( !checkLayerType() ) // check if this one Layer is based on a Table, View or VirtualShapefile
{
// invalid metadata
numberFeatures = 0;
valid = false;
QgsLogger::critical( "Invalid SpatiaLite layer" );
closeDb();
return;
}
enabledCapabilities = QgsVectorDataProvider::SelectAtId | QgsVectorDataProvider::SelectGeometryAtId;
enabledCapabilities |= QgsVectorDataProvider::DeleteFeatures;
enabledCapabilities |= QgsVectorDataProvider::ChangeGeometries;
enabledCapabilities |= QgsVectorDataProvider::ChangeAttributeValues;
enabledCapabilities |= QgsVectorDataProvider::AddFeatures;
enabledCapabilities |= QgsVectorDataProvider::AddAttributes;
if ( mTableBased && !mReadOnly )
{
// enabling editing only for Tables [excluding Views and VirtualShapes]
enabledCapabilities |= QgsVectorDataProvider::DeleteFeatures;
enabledCapabilities |= QgsVectorDataProvider::ChangeGeometries;
enabledCapabilities |= QgsVectorDataProvider::ChangeAttributeValues;
enabledCapabilities |= QgsVectorDataProvider::AddFeatures;
enabledCapabilities |= QgsVectorDataProvider::AddAttributes;
}
if ( !getGeometryDetails() ) // gets srid and geometry type
{
@ -125,7 +139,7 @@ void QgsSpatiaLiteProvider::loadFields()
int fldNo = 0;
attributeFields.clear();
primaryKey.clear();
mPrimaryKey.clear();
QString sql = QString( "PRAGMA table_info(%1)" ).arg( quotedValue( mTableName ) );
@ -148,7 +162,7 @@ void QgsSpatiaLiteProvider::loadFields()
pkName = name;
}
if ( name != geometryColumn )
if ( name != mGeometryColumn )
{
// for sure any SQLite value can be represented as SQLITE_TEXT
QVariant::Type fieldType = QVariant::String;
@ -177,7 +191,7 @@ void QgsSpatiaLiteProvider::loadFields()
if ( pkCount == 1 )
{
// setting the Primary Key column name
primaryKey = pkName;
mPrimaryKey = pkName;
}
return;
@ -214,7 +228,7 @@ bool QgsSpatiaLiteProvider::featureAtId( int featureId, QgsFeature & feature, bo
}
if ( fetchGeometry )
{
sql += QString( ", AsBinary(%1)" ).arg( geometryColumn );
sql += QString( ", AsBinary(%1)" ).arg( mGeometryColumn );
}
sql += QString( " FROM %1 WHERE ROWID = %2" ).arg( quotedValue( mTableName ) ).arg( featureId );
@ -297,7 +311,7 @@ bool QgsSpatiaLiteProvider::featureAtId( int featureId, QgsFeature & feature, bo
}
if ( mFetchGeom )
{
QString geoCol = QString( "AsBinary(%1)" ).arg( geometryColumn );
QString geoCol = QString( "AsBinary(%1)" ).arg( mGeometryColumn );
if ( strcasecmp( geoCol.toUtf8().constData(), sqlite3_column_name( stmt, ic ) ) == 0 )
{
if ( sqlite3_column_type( stmt, ic ) == SQLITE_BLOB )
@ -419,7 +433,7 @@ bool QgsSpatiaLiteProvider::nextFeature( QgsFeature & feature )
}
if ( mFetchGeom )
{
QString geoCol = QString( "AsBinary(%1)" ).arg( geometryColumn );
QString geoCol = QString( "AsBinary(%1)" ).arg( mGeometryColumn );
if ( strcasecmp( geoCol.toUtf8().constData(), sqlite3_column_name( sqliteStatement, ic ) ) == 0 )
{
if ( sqlite3_column_type( sqliteStatement, ic ) == SQLITE_BLOB )
@ -514,7 +528,7 @@ void QgsSpatiaLiteProvider::select( QgsAttributeList fetchAttributes, QgsRectang
}
if ( fetchGeometry )
{
sql += QString( ", AsBinary(%1)" ).arg( geometryColumn );
sql += QString( ", AsBinary(%1)" ).arg( mGeometryColumn );
}
sql += QString( " FROM %1" ).arg( quotedValue( mTableName ) );
@ -531,37 +545,49 @@ void QgsSpatiaLiteProvider::select( QgsAttributeList fetchAttributes, QgsRectang
arg( QString::number( rect.xMinimum(), 'f', 6 ) ).
arg( QString::number( rect.yMinimum(), 'f', 6 ) ).
arg( QString::number( rect.xMaximum(), 'f', 6 ) ).arg( QString::number( rect.yMaximum(), 'f', 6 ) );
whereClause += QString( "Intersects(%1, BuildMbr(%2)) AND " ).arg( geometryColumn ).arg( mbr );
whereClause += QString( "Intersects(%1, BuildMbr(%2)) AND " ).arg( mGeometryColumn ).arg( mbr );
}
if ( spatialIndexRTree )
if ( mVShapeBased )
{
// using the RTree spatial index
QString mbrFilter = QString( "xmin <= %1 AND " ).arg( QString::number( rect.xMaximum(), 'f', 6 ) );
mbrFilter += QString( "xmax >= %1 AND " ).arg( QString::number( rect.xMinimum(), 'f', 6 ) );
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( mTableName ).arg( geometryColumn );
whereClause += QString( "ROWID IN (SELECT pkid FROM %1 WHERE %2)" ).arg( idxName ).arg( mbrFilter );
}
else if ( spatialIndexMbrCache )
{
// using the MbrCache spatial index
// handling a VirtualShape layer
QString mbr = QString( "%1, %2, %3, %4" ).
arg( QString::number( rect.xMinimum(), 'f', 6 ) ).
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( mTableName ).arg( geometryColumn );
whereClause += QString( "ROWID IN (SELECT rowid FROM %1 WHERE mbr = FilterMbrIntersects(%2))" ).arg( idxName ).arg( mbr );
}
else
{
// using simple MBR filtering
QString mbr = QString( "%1, %2, %3, %4" ).
arg( QString::number( rect.xMinimum(), 'f', 6 ) ).
arg( QString::number( rect.yMinimum(), 'f', 6 ) ).
arg( QString::number( rect.xMaximum(), 'f', 6 ) ).arg( QString::number( rect.yMaximum(), 'f', 6 ) );
whereClause += QString( "MbrIntersects(%1, BuildMbr(%2))" ).arg( geometryColumn ).arg( mbr );
}
arg( QString::number( rect.xMinimum(), 'f', 6 ) ).
arg( QString::number( rect.yMinimum(), 'f', 6 ) ).
arg( QString::number( rect.xMaximum(), 'f', 6 ) ).arg( QString::number( rect.yMaximum(), 'f', 6 ) );
whereClause += QString( "MbrIntersects(%1, BuildMbr(%2))" ).arg( mGeometryColumn ).arg( mbr );
}
else
{
if ( spatialIndexRTree )
{
// using the RTree spatial index
QString mbrFilter = QString( "xmin <= %1 AND " ).arg( QString::number( rect.xMaximum(), 'f', 6 ) );
mbrFilter += QString( "xmax >= %1 AND " ).arg( QString::number( rect.xMinimum(), 'f', 6 ) );
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( idxName ).arg( mbrFilter );
}
else if ( spatialIndexMbrCache )
{
// using the MbrCache spatial index
QString mbr = QString( "%1, %2, %3, %4" ).
arg( QString::number( rect.xMinimum(), 'f', 6 ) ).
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( idxName ).arg( mbr );
}
else
{
// using simple MBR filtering
QString mbr = QString( "%1, %2, %3, %4" ).
arg( QString::number( rect.xMinimum(), 'f', 6 ) ).
arg( QString::number( rect.yMinimum(), 'f', 6 ) ).
arg( QString::number( rect.xMaximum(), 'f', 6 ) ).arg( QString::number( rect.yMaximum(), 'f', 6 ) );
whereClause += QString( "MbrIntersects(%1, BuildMbr(%2))" ).arg( mGeometryColumn ).arg( mbr );
}
}
}
if ( !whereClause.isEmpty() )
@ -589,7 +615,6 @@ void QgsSpatiaLiteProvider::select( QgsAttributeList fetchAttributes, QgsRectang
QString msg = tr( "SQLite error: %1\n\nSQL: %2" ).arg( sql ).arg( errCause );
QgsLogger::critical( msg );
sqliteStatement = NULL;
valid = false;
}
}
@ -901,15 +926,15 @@ bool QgsSpatiaLiteProvider::addFeatures( QgsFeatureList & flist )
}
toCommit = true;
if ( !primaryKey.isEmpty() )
if ( !mPrimaryKey.isEmpty() )
{
sql = QString( "INSERT INTO %1 (%2, %3" ).
arg( quotedValue( mTableName ) ).arg( quotedValue( primaryKey ) ).arg( quotedValue( geometryColumn ) );
arg( quotedValue( mTableName ) ).arg( quotedValue( mPrimaryKey ) ).arg( quotedValue( mGeometryColumn ) );
values = QString( ") VALUES (NULL, GeomFromWKB(?, %1)" ).arg( mSrid );
}
else
{
sql = QString( "INSERT INTO %1 (%2" ).arg( quotedValue( mTableName ) ).arg( quotedValue( geometryColumn ) );
sql = QString( "INSERT INTO %1 (%2" ).arg( quotedValue( mTableName ) ).arg( quotedValue( mGeometryColumn ) );
values = QString( ") VALUES (GeomFromWKB(?, %1)" ).arg( mSrid );
}
@ -920,7 +945,7 @@ bool QgsSpatiaLiteProvider::addFeatures( QgsFeatureList & flist )
continue;
QString fieldname = fit->name();
if ( fieldname.isEmpty() || fieldname == geometryColumn || fieldname == primaryKey )
if ( fieldname.isEmpty() || fieldname == mGeometryColumn || fieldname == mPrimaryKey )
continue;
sql += ", ";
@ -965,7 +990,7 @@ bool QgsSpatiaLiteProvider::addFeatures( QgsFeatureList & flist )
continue;
QString fieldname = fit->name();
if ( fieldname.isEmpty() || fieldname == geometryColumn || fieldname == primaryKey )
if ( fieldname.isEmpty() || fieldname == mGeometryColumn || fieldname == mPrimaryKey )
continue;
QVariant::Type type = fit->type();
@ -1286,7 +1311,7 @@ bool QgsSpatiaLiteProvider::changeGeometryValues( QgsGeometryMap & geometry_map
sql =
QString( "UPDATE %1 SET %2 = GeomFromWKB(?, %3) WHERE ROWID = ?" ).
arg( quotedValue( mTableName ) ).arg( quotedValue( geometryColumn ) ).arg( mSrid );
arg( quotedValue( mTableName ) ).arg( quotedValue( mGeometryColumn ) ).arg( mSrid );
// SQLite prepared statement
if ( sqlite3_prepare_v2( sqliteHandle, sql.toUtf8().constData(), -1, &stmt, NULL ) != SQLITE_OK )
@ -1379,6 +1404,31 @@ void QgsSpatiaLiteProvider::closeDb()
}
}
bool QgsSpatiaLiteProvider::SqliteHandles::checkMetadata( sqlite3 *handle )
{
int ret;
int i;
char **results;
int rows;
int columns;
int spatial_type = 0;
ret = sqlite3_get_table( handle, "SELECT CheckSpatialMetadata()", &results, &rows, &columns, NULL );
if (ret != SQLITE_OK)
goto skip;
if (rows < 1)
;
else
{
for (i = 1; i <= rows; i++)
spatial_type = atoi(results[(i * columns) + 0]);
}
sqlite3_free_table(results);
skip:
if (spatial_type == 1)
return true;
return false;
}
QgsSpatiaLiteProvider::SqliteHandles * QgsSpatiaLiteProvider::SqliteHandles::openDb( const QString & dbPath )
{
sqlite3 *sqlite_handle;
@ -1402,6 +1452,20 @@ QgsSpatiaLiteProvider::SqliteHandles * QgsSpatiaLiteProvider::SqliteHandles::ope
QgsLogger::critical( msg );
return NULL;
}
// checking the DB for sanity
if (checkMetadata( sqlite_handle) == false)
{
// failure
QString errCause = tr ( "invalid metadata tables" );
QString msg = tr( "Failure while connecting to: %1\n\n%2" ).arg( dbPath ).arg( errCause );
QgsLogger::critical( msg );
sqlite3_close( sqlite_handle );
return NULL;
}
// activating Foreign Key constraints
sqlite3_exec(sqlite_handle, "PRAGMA foreign_keys = 1", NULL, 0, NULL);
QgsDebugMsg( "Connection to the database was successful" );
@ -1453,7 +1517,7 @@ QString QgsSpatiaLiteProvider::quotedValue( QString value ) const
return value.prepend( "'" ).append( "'" );
}
bool QgsSpatiaLiteProvider::getGeometryDetails()
bool QgsSpatiaLiteProvider::checkLayerType()
{
int ret;
int i;
@ -1461,10 +1525,121 @@ bool QgsSpatiaLiteProvider::getGeometryDetails()
int rows;
int columns;
char *errMsg = NULL;
int count = 0;
mTableBased = false;
mViewBased = false;
mVShapeBased = 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 ) );
ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )
goto error;
if ( rows < 1 )
;
else
{
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++;
}
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 )
goto error;
if ( rows < 1 )
;
else
{
mViewBased = true;
mReadOnly = true;
count++;
}
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 )
goto error;
if ( rows < 1 )
;
else
{
mVShapeBased = true;
mReadOnly = true;
count++;
}
sqlite3_free_table( results );
// cheching for validity
if (count != 1)
return false;
return true;
error:
// unexpected error
if ( errMsg != NULL )
{
QString errCause = errMsg;
QString msg = QString( "checkLayerType SQL error: %1\n\n%2" ).arg( sql ).arg( errCause );
QgsLogger::critical( msg );
sqlite3_free( errMsg );
}
return false;
}
bool QgsSpatiaLiteProvider::getGeometryDetails()
{
bool ret = false;
if ( mTableBased )
ret = getTableGeometryDetails();
if ( mViewBased )
ret = getViewGeometryDetails();
if ( mVShapeBased )
ret = getVShapeGeometryDetails();
return ret;
}
bool QgsSpatiaLiteProvider::getTableGeometryDetails()
{
int ret;
int i;
char **results;
int rows;
int columns;
char *errMsg = NULL;
mIndexTable = mTableName;
mIndexGeometry = mGeometryColumn;
QString sql = QString( "SELECT type, srid, spatial_index_enabled FROM geometry_columns"
" WHERE f_table_name=%1 and f_geometry_column=%2" ).arg( quotedValue( mTableName ) ).
arg( quotedValue( geometryColumn ) );
arg( quotedValue( mGeometryColumn ) );
ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )
@ -1519,8 +1694,188 @@ bool QgsSpatiaLiteProvider::getGeometryDetails()
if ( geomType == QGis::WKBUnknown || mSrid < 0 )
goto error;
return getSridDetails();
sql = QString( "SELECT proj4text FROM spatial_ref_sys WHERE srid=%1" ).arg( mSrid );
error:
// unexpected error
if ( errMsg != NULL )
{
QString errCause = errMsg;
QString msg = QString( "getTableGeometryDetails SQL error: %1\n\n%2" ).arg( sql ).arg( errCause );
QgsLogger::critical( msg );
sqlite3_free( errMsg );
}
return false;
}
bool QgsSpatiaLiteProvider::getViewGeometryDetails()
{
int ret;
int i;
char **results;
int rows;
int columns;
char *errMsg = NULL;
QString sql = QString( "SELECT type, srid, spatial_index_enabled, f_table_name, f_geometry_column "
" FROM views_geometry_columns"
" JOIN geometry_columns USING (f_table_name, f_geometry_column)"
" 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 )
goto error;
if ( rows < 1 )
;
else
{
for ( i = 1; i <= rows; i++ )
{
QString fType = results[( i * columns ) + 0];
QString xSrid = results[( i * columns ) + 1];
QString spatialIndex = results[( i * columns ) + 2];
mIndexTable = results[( i * columns ) + 3];
mIndexGeometry = results[( i * columns ) + 4];
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 ( spatialIndex.toInt() == 1 )
{
spatialIndexRTree = true;
}
if ( spatialIndex.toInt() == 2 )
{
spatialIndexMbrCache = true;
}
}
}
sqlite3_free_table( results );
if ( geomType == QGis::WKBUnknown || mSrid < 0 )
goto error;
return getSridDetails();
error:
// unexpected error
if ( errMsg != NULL )
{
QString errCause = errMsg;
QString msg = QString( "getViewGeometryDetails SQL error: %1\n\n%2" ).arg( sql ).arg( errCause );
QgsLogger::critical( msg );
sqlite3_free( errMsg );
}
return false;
}
bool QgsSpatiaLiteProvider::getVShapeGeometryDetails()
{
int ret;
int i;
char **results;
int rows;
int columns;
char *errMsg = NULL;
QString sql = QString( "SELECT type, srid 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 )
goto error;
if ( rows < 1 )
;
else
{
for ( i = 1; i <= rows; i++ )
{
QString fType = results[( i * columns ) + 0];
QString xSrid = results[( i * columns ) + 1];
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();
}
}
sqlite3_free_table( results );
if ( geomType == QGis::WKBUnknown || mSrid < 0 )
goto error;
return getSridDetails();
error:
// unexpected error
if ( errMsg != NULL )
{
QString errCause = errMsg;
QString msg = QString( "getVShapeGeometryDetails SQL error: %1\n\n%2" ).arg( sql ).arg( errCause );
QgsLogger::critical( msg );
sqlite3_free( errMsg );
}
return false;
}
bool QgsSpatiaLiteProvider::getSridDetails()
{
int ret;
int i;
char **results;
int rows;
int columns;
char *errMsg = NULL;
QString sql = QString( "SELECT proj4text FROM spatial_ref_sys WHERE srid=%1" ).arg( mSrid );
ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )
@ -1543,7 +1898,7 @@ error:
if ( errMsg != NULL )
{
QString errCause = errMsg;
QString msg = QString( "getGeometryDetails SQL error: %1\n\n%2" ).arg( sql ).arg( errCause );
QString msg = QString( "getSridDetails SQL error: %1\n\n%2" ).arg( sql ).arg( errCause );
QgsLogger::critical( msg );
sqlite3_free( errMsg );
}
@ -1560,7 +1915,7 @@ bool QgsSpatiaLiteProvider::getTableSummary()
char *errMsg = NULL;
QString sql = QString( "SELECT Min(MbrMinX(%1)), Min(MbrMinY(%1)), "
"Max(MbrMaxX(%1)), Max(MbrMaxY(%1)), Count(*) " "FROM %2" ).arg( geometryColumn ).arg( quotedValue( mTableName ) );
"Max(MbrMaxX(%1)), Max(MbrMaxY(%1)), Count(*) " "FROM %2" ).arg( mGeometryColumn ).arg( quotedValue( mTableName ) );
if ( !mSubsetString.isEmpty() )
{
@ -1617,7 +1972,7 @@ const QgsField & QgsSpatiaLiteProvider::field( int index ) const
/**
* Class factory to return a pointer to a newly created
* QgsPostgresProvider object
* QgsSpatiaLiteProvider object
*/
QGISEXTERN QgsSpatiaLiteProvider *classFactory( const QString * uri )
{

View File

@ -143,9 +143,7 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
*/
const QgsFieldMap & fields() const;
/** Reset the layer - for a PostgreSQL layer, this means clearing the PQresult
* pointer, setting it to 0 and reloading the field list
*/
/** Reset the layer */
void rewind();
/** Returns the minimum value of an attribute
@ -241,7 +239,7 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
signals:
/**
* This is emitted whenever the worker thread has fully calculated the
* PostGIS extents for this layer, and its event has been received by this
* extents for this layer, and its event has been received by this
* provider.
*/
void fullExtentCalculated();
@ -267,6 +265,22 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
* 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 plain Table
*/
bool mTableBased;
/**
* Flag indicating if the layer data source is based on a View
*/
bool mViewBased;
/**
* Flag indicating if the layer data source is based on a VirtualShape
*/
bool mVShapeBased;
/**
* Flag indicating if the layer data source has ReadOnly restrictions
*/
bool mReadOnly;
/**
* DB full path
*/
@ -278,11 +292,19 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
/**
* Name of the primary key column in the table
*/
QString primaryKey;
QString mPrimaryKey;
/**
* Name of the geometry column in the table
*/
QString geometryColumn;
QString mGeometryColumn;
/**
* Name of the SpatialIndex table
*/
QString mIndexTable;
/**
* Name of the SpatialIndex geometry column
*/
QString mIndexGeometry;
/**
* Geometry type
*/
@ -335,7 +357,12 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
//void sqliteOpen();
void closeDb();
QString quotedValue( QString value ) const;
bool checkLayerType();
bool getGeometryDetails();
bool getTableGeometryDetails();
bool getViewGeometryDetails();
bool getVShapeGeometryDetails();
bool getSridDetails();
bool getTableSummary();
public:
@ -361,6 +388,7 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
void sqliteClose();
static SqliteHandles *openDb( const QString & dbPath );
static bool checkMetadata( sqlite3 * handle );
static void closeDb( SqliteHandles * &handle );
static void closeDb( QMap < QString, SqliteHandles * >&handlesRO, SqliteHandles * &handle );

View File

@ -1,42 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<ui version="4.0" >
<class>QgsSpatiaLiteSourceSelectBase</class>
<widget class="QDialog" name="QgsSpatiaLiteSourceSelectBase">
<property name="geometry">
<widget class="QDialog" name="QgsSpatiaLiteSourceSelectBase" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>472</width>
<width>672</width>
<height>687</height>
</rect>
</property>
<property name="windowTitle">
<property name="windowTitle" >
<string>Add SpatiaLite Table(s)</string>
</property>
<property name="windowIcon">
<property name="windowIcon" >
<iconset>
<normaloff/>
</iconset>
</property>
<property name="sizeGripEnabled">
<property name="sizeGripEnabled" >
<bool>true</bool>
</property>
<property name="modal">
<property name="modal" >
<bool>true</bool>
</property>
<layout class="QGridLayout">
<property name="margin">
<layout class="QGridLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing">
<property name="spacing" >
<number>6</number>
</property>
<item row="2" column="0">
<item row="2" column="0" >
<spacer>
<property name="orientation">
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>271</width>
<height>20</height>
@ -44,150 +43,202 @@
</property>
</spacer>
</item>
<item row="1" column="0" colspan="2">
<widget class="QTreeView" name="mTablesTreeView">
<property name="selectionMode">
<item row="1" column="0" colspan="2" >
<widget class="QTreeView" name="mTablesTreeView" >
<property name="selectionMode" >
<enum>QAbstractItemView::MultiSelection</enum>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<item row="0" column="0" colspan="2" >
<widget class="QGroupBox" name="groupBox" >
<property name="title" >
<string>SpatiaLite DBs</string>
</property>
<layout class="QGridLayout">
<property name="margin">
<layout class="QGridLayout" >
<property name="margin" >
<number>11</number>
</property>
<property name="spacing">
<property name="spacing" >
<number>6</number>
</property>
<item row="1" column="2">
<widget class="QPushButton" name="btnDelete">
<property name="text">
<item row="1" column="2" >
<widget class="QPushButton" name="btnDelete" >
<property name="text" >
<string>Delete</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="btnNew">
<property name="text">
<item row="1" column="1" >
<widget class="QPushButton" name="btnNew" >
<property name="text" >
<string>New</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="btnConnect">
<property name="text">
<item row="1" column="0" >
<widget class="QPushButton" name="btnConnect" >
<property name="text" >
<string>Connect</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="3">
<widget class="QComboBox" name="cmbConnections"/>
<item row="0" column="0" colspan="3" >
<widget class="QComboBox" name="cmbConnections" />
</item>
</layout>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QGroupBox" name="mSearchGroupBox">
<property name="title">
<item row="4" column="0" colspan="2" >
<layout class="QHBoxLayout" >
<property name="margin" >
<number>11</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QPushButton" name="btnHelp" >
<property name="enabled" >
<bool>true</bool>
</property>
<property name="text" >
<string>Help</string>
</property>
<property name="shortcut" >
<string>F1</string>
</property>
<property name="autoDefault" >
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType" >
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" >
<size>
<width>141</width>
<height>21</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnAdd" >
<property name="text" >
<string>Add</string>
</property>
<property name="shortcut" >
<string/>
</property>
<property name="autoDefault" >
<bool>true</bool>
</property>
<property name="default" >
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnCancel" >
<property name="text" >
<string>Close</string>
</property>
<property name="shortcut" >
<string/>
</property>
<property name="autoDefault" >
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0" colspan="2" >
<widget class="QGroupBox" name="mSearchGroupBox" >
<property name="title" >
<string/>
</property>
<layout class="QGridLayout">
<property name="margin">
<layout class="QGridLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing">
<property name="spacing" >
<number>6</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="mSearchLabel">
<property name="text">
<item row="0" column="0" >
<widget class="QLabel" name="mSearchLabel" >
<property name="text" >
<string>Search:</string>
</property>
<property name="buddy">
<cstring>mSearchTableEdit</cstring>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="mSearchModeLabel">
<property name="text">
<item row="2" column="0" colspan="2" >
<widget class="QLabel" name="mSearchModeLabel" >
<property name="text" >
<string>Search mode:</string>
</property>
<property name="buddy">
<cstring>mSearchModeComboBox</cstring>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QComboBox" name="mSearchModeComboBox"/>
<item row="2" column="2" >
<widget class="QComboBox" name="mSearchModeComboBox" />
</item>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="mSearchColumnsLabel">
<property name="text">
<item row="1" column="0" colspan="2" >
<widget class="QLabel" name="mSearchColumnsLabel" >
<property name="text" >
<string>Search in columns:</string>
</property>
<property name="buddy">
<cstring>mSearchColumnComboBox</cstring>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QComboBox" name="mSearchColumnComboBox"/>
<item row="1" column="2" >
<widget class="QComboBox" name="mSearchColumnComboBox" />
</item>
<item row="0" column="1" colspan="2">
<widget class="QLineEdit" name="mSearchTableEdit"/>
<item row="0" column="1" colspan="2" >
<widget class="QLineEdit" name="mSearchTableEdit" />
</item>
</layout>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="mSearchOptionsButton">
<property name="text">
<item row="2" column="1" >
<widget class="QPushButton" name="mSearchOptionsButton" >
<property name="text" >
<string>Search options...</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Close|QDialogButtonBox::Help</set>
</property>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<layoutdefault spacing="6" margin="11" />
<tabstops>
<tabstop>cmbConnections</tabstop>
<tabstop>btnConnect</tabstop>
<tabstop>btnNew</tabstop>
<tabstop>btnDelete</tabstop>
<tabstop>mTablesTreeView</tabstop>
<tabstop>mSearchOptionsButton</tabstop>
<tabstop>mSearchTableEdit</tabstop>
<tabstop>mSearchColumnComboBox</tabstop>
<tabstop>mSearchModeComboBox</tabstop>
<tabstop>buttonBox</tabstop>
<tabstop>btnHelp</tabstop>
<tabstop>btnAdd</tabstop>
<tabstop>btnCancel</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<sender>btnCancel</sender>
<signal>clicked()</signal>
<receiver>QgsSpatiaLiteSourceSelectBase</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>431</x>
<y>666</y>
<hint type="sourcelabel" >
<x>404</x>
<y>446</y>
</hint>
<hint type="destinationlabel">
<x>465</x>
<y>527</y>
<hint type="destinationlabel" >
<x>229</x>
<y>236</y>
</hint>
</hints>
</connection>