Skip to content

Instantly share code, notes, and snippets.

@kiselev-dv
Created January 8, 2016 09:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kiselev-dv/5f4db4447b78330e5b63 to your computer and use it in GitHub Desktop.
Save kiselev-dv/5f4db4447b78330e5b63 to your computer and use it in GitHub Desktop.
/***************************************************************************
qgsosmdatabase.cpp
--------------------------------------
Date : January 2013
Copyright : (C) 2013 by Martin Dobias
Email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsosmdatabase.h"
#include <spatialite.h>
#include "qgsgeometry.h"
#include "qgslogger.h"
QgsOSMDatabase::QgsOSMDatabase( const QString& dbFileName )
: mDbFileName( dbFileName )
, mDatabase( 0 )
, mStmtNode( 0 )
, mStmtNodeTags( 0 )
, mStmtWay( 0 )
, mStmtWayNode( 0 )
, mStmtWayNodePoints( 0 )
, mStmtWayTags( 0 )
{
}
QgsOSMDatabase::~QgsOSMDatabase()
{
if ( isOpen() )
close();
}
bool QgsOSMDatabase::isOpen() const
{
return mDatabase != 0;
}
bool QgsOSMDatabase::open()
{
// load spatialite extension
spatialite_init( 0 );
// open database
int res = sqlite3_open_v2( mDbFileName.toUtf8().data(), &mDatabase, SQLITE_OPEN_READWRITE, 0 );
if ( res != SQLITE_OK )
{
mError = QString( "Failed to open database [%1]: %2" ).arg( res ).arg( mDbFileName );
close();
return false;
}
if ( !prepareStatements() )
{
close();
return false;
}
return true;
}
void QgsOSMDatabase::deleteStatement( sqlite3_stmt*& stmt )
{
if ( stmt )
{
sqlite3_finalize( stmt );
stmt = 0;
}
}
bool QgsOSMDatabase::close()
{
deleteStatement( mStmtNode );
deleteStatement( mStmtNodeTags );
deleteStatement( mStmtWay );
deleteStatement( mStmtWayNode );
deleteStatement( mStmtWayNodePoints );
deleteStatement( mStmtWayTags );
Q_ASSERT( mStmtNode == 0 );
// close database
if ( sqlite3_close( mDatabase ) != SQLITE_OK )
{
//mError = ( char * ) "Closing SQLite3 database failed.";
//return false;
}
mDatabase = 0;
return true;
}
int QgsOSMDatabase::runCountStatement( const char* sql ) const
{
sqlite3_stmt* stmt;
int res = sqlite3_prepare_v2( mDatabase, sql, -1, &stmt, 0 );
if ( res != SQLITE_OK )
return -1;
res = sqlite3_step( stmt );
if ( res != SQLITE_ROW )
return -1;
int count = sqlite3_column_int( stmt, 0 );
sqlite3_finalize( stmt );
return count;
}
int QgsOSMDatabase::countNodes() const
{
return runCountStatement( "SELECT count(*) FROM nodes" );
}
int QgsOSMDatabase::countWays() const
{
return runCountStatement( "SELECT count(*) FROM ways" );
}
QgsOSMNodeIterator QgsOSMDatabase::listNodes() const
{
return QgsOSMNodeIterator( mDatabase );
}
QgsOSMWayIterator QgsOSMDatabase::listWays() const
{
return QgsOSMWayIterator( mDatabase );
}
QgsOSMNode QgsOSMDatabase::node( QgsOSMId id ) const
{
// bind the way identifier
sqlite3_bind_int64( mStmtNode, 1, id );
if ( sqlite3_step( mStmtNode ) != SQLITE_ROW )
{
//QgsDebugMsg( "Cannot get number of way members." );
sqlite3_reset( mStmtNode );
return QgsOSMNode();
}
double lon = sqlite3_column_double( mStmtNode, 0 );
double lat = sqlite3_column_double( mStmtNode, 1 );
QgsOSMNode node( id, QgsPoint( lon, lat ) );
sqlite3_reset( mStmtNode );
return node;
}
QgsOSMTags QgsOSMDatabase::tags( bool way, QgsOSMId id ) const
{
QgsOSMTags t;
sqlite3_stmt* stmtTags = way ? mStmtWayTags : mStmtNodeTags;
sqlite3_bind_int64( stmtTags, 1, id );
while ( sqlite3_step( stmtTags ) == SQLITE_ROW )
{
QString k = QString::fromUtf8(( const char* ) sqlite3_column_text( stmtTags, 0 ) );
QString v = QString::fromUtf8(( const char* ) sqlite3_column_text( stmtTags, 1 ) );
t.insert( k, v );
}
sqlite3_reset( stmtTags );
return t;
}
QList<QgsOSMTagCountPair> QgsOSMDatabase::usedTags( bool ways ) const
{
QList<QgsOSMTagCountPair> pairs;
QString sql = QString( "SELECT k, count(k) FROM %1_tags GROUP BY k" ).arg( ways ? "ways" : "nodes" );
sqlite3_stmt* stmt;
if ( sqlite3_prepare_v2( mDatabase, sql.toUtf8().data(), -1, &stmt, 0 ) != SQLITE_OK )
return pairs;
while ( sqlite3_step( stmt ) == SQLITE_ROW )
{
QString k = QString::fromUtf8(( const char* ) sqlite3_column_text( stmt, 0 ) );
int count = sqlite3_column_int( stmt, 1 );
pairs.append( qMakePair( k, count ) );
}
sqlite3_finalize( stmt );
return pairs;
}
QgsOSMWay QgsOSMDatabase::way( QgsOSMId id ) const
{
// TODO: first check that way exists!
// mStmtWay
// bind the way identifier
sqlite3_bind_int64( mStmtWayNode, 1, id );
QList<QgsOSMId> nodes;
while ( sqlite3_step( mStmtWayNode ) == SQLITE_ROW )
{
QgsOSMId nodeId = sqlite3_column_int64( mStmtWayNode, 0 );
nodes.append( nodeId );
}
sqlite3_reset( mStmtWayNode );
if ( nodes.isEmpty() )
return QgsOSMWay();
return QgsOSMWay( id, nodes );
}
/*
OSMRelation OSMDatabase::relation( OSMId id ) const
{
// todo
Q_UNUSED(id);
return OSMRelation();
}*/
QgsPolyline QgsOSMDatabase::wayPoints( QgsOSMId id ) const
{
QgsPolyline points;
// bind the way identifier
sqlite3_bind_int64( mStmtWayNodePoints, 1, id );
while ( sqlite3_step( mStmtWayNodePoints ) == SQLITE_ROW )
{
if ( sqlite3_column_type( mStmtWayNodePoints, 0 ) == SQLITE_NULL )
return QgsPolyline(); // missing some nodes
double lon = sqlite3_column_double( mStmtWayNodePoints, 0 );
double lat = sqlite3_column_double( mStmtWayNodePoints, 1 );
points.append( QgsPoint( lon, lat ) );
}
sqlite3_reset( mStmtWayNodePoints );
return points;
}
bool QgsOSMDatabase::prepareStatements()
{
const char* sql[] =
{
"SELECT lon,lat FROM nodes WHERE id=?",
"SELECT k,v FROM nodes_tags WHERE id=?",
"SELECT id FROM ways WHERE id=?",
"SELECT node_id FROM ways_nodes WHERE way_id=? ORDER BY way_pos",
"SELECT n.lon, n.lat FROM ways_nodes wn LEFT JOIN nodes n ON wn.node_id = n.id WHERE wn.way_id=? ORDER BY wn.way_pos",
"SELECT k,v FROM ways_tags WHERE id=?"
};
sqlite3_stmt** sqlite[] =
{
&mStmtNode,
&mStmtNodeTags,
&mStmtWay,
&mStmtWayNode,
&mStmtWayNodePoints,
&mStmtWayTags,
};
int count = sizeof( sql ) / sizeof( const char* );
Q_ASSERT( count == sizeof( sqlite ) / sizeof( sqlite3_stmt** ) );
for ( int i = 0; i < count; ++i )
{
if ( sqlite3_prepare_v2( mDatabase, sql[i], -1, sqlite[i], 0 ) != SQLITE_OK )
{
const char* errMsg = sqlite3_errmsg( mDatabase ); // does not require free
mError = QString( "Error preparing SQL command:\n%1\nSQL:\n%2" )
.arg( QString::fromUtf8( errMsg ) ).arg( QString::fromUtf8( sql[i] ) );
return false;
}
}
return true;
}
bool QgsOSMDatabase::exportSpatiaLite( ExportType type, const QString& tableName,
const QStringList& tagKeys,
const QStringList& notNullTagKeys )
{
mError.clear();
// create SpatiaLite table
QString geometryType;
if ( type == Point ) geometryType = "POINT";
else if ( type == Polyline ) geometryType = "LINESTRING";
else if ( type == Polygon ) geometryType = "POLYGON";
else Q_ASSERT( false && "Unknown export type" );
if ( !createSpatialTable( tableName, geometryType, tagKeys ) )
return false;
// import data
int retX = sqlite3_exec( mDatabase, "BEGIN", NULL, NULL, 0 );
Q_ASSERT( retX == SQLITE_OK );
Q_UNUSED( retX );
if ( type == Polyline || type == Polygon )
exportSpatiaLiteWays( type == Polygon, tableName, tagKeys, notNullTagKeys );
else if ( type == Point )
exportSpatiaLiteNodes( tableName, tagKeys, notNullTagKeys );
else
Q_ASSERT( false && "Unknown export type" );
int retY = sqlite3_exec( mDatabase, "COMMIT", NULL, NULL, 0 );
Q_ASSERT( retY == SQLITE_OK );
Q_UNUSED( retY );
if ( !createSpatialIndex( tableName ) )
return false;
saveExportedTable(tableName, geometryType, tagKeys, notNullTagKeys);
return mError.isEmpty();
}
bool QgsOSMDatabase::createSpatialTable( const QString& tableName, const QString& geometryType, const QStringList& tagKeys )
{
QString sqlCreateTable = QString( "CREATE TABLE %1 (id INTEGER PRIMARY KEY" ).arg( quotedIdentifier( tableName ) );
for ( int i = 0; i < tagKeys.count(); ++i )
sqlCreateTable += QString( ", %1 TEXT" ).arg( quotedIdentifier( tagKeys[i] ) );
sqlCreateTable += ")";
char *errMsg = NULL;
int ret = sqlite3_exec( mDatabase, sqlCreateTable.toUtf8().constData(), NULL, NULL, &errMsg );
if ( ret != SQLITE_OK )
{
mError = "Unable to create table:\n" + QString::fromUtf8( errMsg );
sqlite3_free( errMsg );
return false;
}
QString sqlAddGeomColumn = QString( "SELECT AddGeometryColumn(%1, 'geometry', 4326, %2, 'XY')" )
.arg( quotedValue( tableName ) )
.arg( quotedValue( geometryType ) );
ret = sqlite3_exec( mDatabase, sqlAddGeomColumn.toUtf8().constData(), NULL, NULL, &errMsg );
if ( ret != SQLITE_OK )
{
mError = "Unable to add geometry column:\n" + QString::fromUtf8( errMsg );
sqlite3_free( errMsg );
return false;
}
return true;
}
bool QgsOSMDatabase::createSpatialIndex( const QString& tableName )
{
QString sqlSpatialIndex = QString( "SELECT CreateSpatialIndex(%1, 'geometry')" ).arg( quotedValue( tableName ) );
char *errMsg = NULL;
int ret = sqlite3_exec( mDatabase, sqlSpatialIndex.toUtf8().constData(), NULL, NULL, &errMsg );
if ( ret != SQLITE_OK )
{
mError = "Unable to create spatial index:\n" + QString::fromUtf8( errMsg );
sqlite3_free( errMsg );
return false;
}
return true;
}
void QgsOSMDatabase::exportSpatiaLiteNodes( const QString& tableName, const QStringList& tagKeys, const QStringList& notNullTagKeys )
{
QString sqlInsertPoint = QString( "INSERT INTO %1 VALUES (?" ).arg( quotedIdentifier( tableName ) );
for ( int i = 0; i < tagKeys.count(); ++i )
sqlInsertPoint += QString( ",?" );
sqlInsertPoint += ", GeomFromWKB(?, 4326))";
sqlite3_stmt* stmtInsert;
if ( sqlite3_prepare_v2( mDatabase, sqlInsertPoint.toUtf8().constData(), -1, &stmtInsert, 0 ) != SQLITE_OK )
{
mError = "Prepare SELECT FROM nodes failed.";
return;
}
QgsOSMNodeIterator nodes = listNodes();
QgsOSMNode n;
while (( n = nodes.next() ).isValid() )
{
QgsOSMTags t = tags( false, n.id() );
// skip untagged nodes: probably they form a part of ways
if ( t.count() == 0 )
continue;
//check not null tags
bool skipNull = false;
for ( int i = 0; i < notNullTagKeys.count() && !skipNull; ++i )
if ( !t.contains( notNullTagKeys[i] ) )
skipNull = true;
if ( skipNull )
continue;
QgsGeometry* geom = QgsGeometry::fromPoint( n.point() );
int col = 0;
sqlite3_bind_int64( stmtInsert, ++col, n.id() );
// tags
for ( int i = 0; i < tagKeys.count(); ++i )
{
if ( t.contains( tagKeys[i] ) )
sqlite3_bind_text( stmtInsert, ++col, t.value( tagKeys[i] ).toUtf8().constData(), -1, SQLITE_TRANSIENT );
else
sqlite3_bind_null( stmtInsert, ++col );
}
sqlite3_bind_blob( stmtInsert, ++col, geom->asWkb(), ( int ) geom->wkbSize(), SQLITE_STATIC );
int insertRes = sqlite3_step( stmtInsert );
if ( insertRes != SQLITE_DONE )
{
mError = QString( "Error inserting node %1 [%2]" ).arg( n.id() ).arg( insertRes );
delete geom;
break;
}
sqlite3_reset( stmtInsert );
sqlite3_clear_bindings( stmtInsert );
delete geom;
}
sqlite3_finalize( stmtInsert );
}
void QgsOSMDatabase::exportSpatiaLiteWays( bool closed, const QString& tableName,
const QStringList& tagKeys,
const QStringList& notNullTagKeys )
{
Q_UNUSED( tagKeys );
QString sqlInsertLine = QString( "INSERT INTO %1 VALUES (?" ).arg( quotedIdentifier( tableName ) );
for ( int i = 0; i < tagKeys.count(); ++i )
sqlInsertLine += QString( ",?" );
sqlInsertLine += ", GeomFromWKB(?, 4326))";
sqlite3_stmt* stmtInsert;
if ( sqlite3_prepare_v2( mDatabase, sqlInsertLine.toUtf8().constData(), -1, &stmtInsert, 0 ) != SQLITE_OK )
{
mError = "Prepare SELECT FROM ways failed.";
return;
}
QgsOSMWayIterator ways = listWays();
QgsOSMWay w;
while (( w = ways.next() ).isValid() )
{
QgsOSMTags t = tags( true, w.id() );
QgsPolyline polyline = wayPoints( w.id() );
if ( polyline.count() < 2 )
continue; // invalid way
bool isArea = ( polyline.first() == polyline.last() ); // closed way?
// some closed ways are not really areas
if ( isArea && ( t.contains( "highway" ) || t.contains( "barrier" ) ) )
{
if ( t.value( "area" ) != "yes" ) // even though "highway" is line by default, "area"="yes" may override that
isArea = false;
}
if ( closed != isArea )
continue; // skip if it's not what we're looking for
//check not null tags
bool skipNull = false;
for ( int i = 0; i < notNullTagKeys.count() && !skipNull; ++i )
if ( !t.contains( notNullTagKeys[i] ) )
skipNull = true;
if ( skipNull )
continue;
QgsGeometry* geom = closed ? QgsGeometry::fromPolygon( QgsPolygon() << polyline ) : QgsGeometry::fromPolyline( polyline );
int col = 0;
sqlite3_bind_int64( stmtInsert, ++col, w.id() );
// tags
for ( int i = 0; i < tagKeys.count(); ++i )
{
if ( t.contains( tagKeys[i] ) )
sqlite3_bind_text( stmtInsert, ++col, t.value( tagKeys[i] ).toUtf8().constData(), -1, SQLITE_TRANSIENT );
else
sqlite3_bind_null( stmtInsert, ++col );
}
if ( geom )
sqlite3_bind_blob( stmtInsert, ++col, geom->asWkb(), ( int ) geom->wkbSize(), SQLITE_STATIC );
else
sqlite3_bind_null( stmtInsert, ++col );
int insertRes = sqlite3_step( stmtInsert );
if ( insertRes != SQLITE_DONE )
{
mError = QString( "Error inserting way %1 [%2]" ).arg( w.id() ).arg( insertRes );
delete geom;
break;
}
sqlite3_reset( stmtInsert );
sqlite3_clear_bindings( stmtInsert );
delete geom;
}
sqlite3_finalize( stmtInsert );
}
bool QgsOSMDatabase::saveExportedTable(const QString &tableName, const QString &geometryType, const QStringList &tagKeys, const QStringList &notNullTagKeys)
{
return saveExportedTable2DB( tableName, geometryType, tagKeys, notNullTagKeys )
&& saveExportedTable2Proj( tableName, geometryType, tagKeys, notNullTagKeys );
}
bool QgsOSMDatabase::saveExportedTable2DB(const QString &tableName, const QString &geometryType, const QStringList &tagKeys, const QStringList &notNullTagKeys)
{
if(!createExportsTable())
return false;
//Save table (layer)
QString insertTable = QString("INSERT INTO QGIS_OSM_EXPORTS_TABLES (name, type) VALUES(?, ?)");
sqlite3_stmt* stmtTableInsert;
if ( sqlite3_prepare_v2( mDatabase, insertTable.toUtf8().constData(), -1, &stmtTableInsert, 0 ) != SQLITE_OK )
{
mError = "Prepare INSERT into QGIS_OSM_EXPORTS_TABLES failed.";
return false;
}
sqlite3_bind_text(stmtTableInsert, 1, quotedValue( tableName ).toUtf8().constData(), -1, SQLITE_TRANSIENT );
sqlite3_bind_text(stmtTableInsert, 2, quotedValue( geometryType ).toUtf8().constData(), -1, SQLITE_TRANSIENT );
int insertRes = sqlite3_step( stmtTableInsert );
if ( insertRes != SQLITE_DONE )
{
mError = QString( "Error saving %1 metainfo to DB").arg(tableName);
return false;
}
sqlite3_reset( stmtTableInsert );
sqlite3_clear_bindings( stmtTableInsert );
//Save columns (used OSM tags)
QString insertColumns = QString("INSERT INTO QGIS_OSM_EXPORTS_COLUMNS (layer, column, tag, isNotNll) values (?, ?, ?, ?) ");
sqlite3_stmt* stmtColumnsInsert;
if ( sqlite3_prepare_v2( mDatabase, insertColumns.toUtf8().constData(), -1, &stmtColumnsInsert, 0 ) != SQLITE_OK )
{
mError = "Prepare INSERT into QGIS_OSM_EXPORTS_COLUMNS failed.";
return false;
}
bindColumnsToInsert(stmtColumnsInsert, tableName, tagKeys, 0);
bindColumnsToInsert(stmtColumnsInsert, tableName, notNullTagKeys, 1);
return mError.isEmpty();
}
void QgsOSMDatabase::bindColumnsToInsert(sqlite3_stmt* stmtColumnsInsert, const QString &tableName, const QStringList &tagKeys, int notNull)
{
for(int i = 0; i < tagKeys.count(); i++)
{
sqlite3_bind_text(stmtColumnsInsert, 1, quotedValue( tableName ).toUtf8().constData(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmtColumnsInsert, 2, quotedValue( tagKeys[i] ).toUtf8().constData(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmtColumnsInsert, 3, quotedValue( tagKeys[i] ).toUtf8().constData(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmtColumnsInsert, 4, notNull);
int insertRes = sqlite3_step( stmtColumnsInsert );
if ( insertRes != SQLITE_DONE )
{
mError = QString( "Error saving %1 metainfo to DB").arg(tableName);
}
sqlite3_reset( stmtColumnsInsert );
sqlite3_clear_bindings( stmtColumnsInsert );
}
}
bool QgsOSMDatabase::saveExportedTable2Proj(const QString &tableName, const QString &geometryType, const QStringList &tagKeys, const QStringList &notNullTagKeys)
{
QStringList layers = QStringList();
QgsProject::instance()->readListEntry( QString("OSMSpatialLiteExport"), QString("/layers"), layers );
layers << tableName;
layers.removeDuplicates();
QgsProject::instance()->writeEntry( QString("OSMSpatialLiteExport"), QString("/layers"), layers );
QgsProject::instance()->writeEntry( QString("OSMSpatialLiteExport"), QString("/layer/%1/type").arg(tableName), geometryType );
QgsProject::instance()->writeEntry( QString("OSMSpatialLiteExport"), QString("/layer/%1/tagKeys").arg(tableName), tagKeys );
QgsProject::instance()->writeEntry( QString("OSMSpatialLiteExport"), QString("/layer/%1/notNullTagKeys").arg(tableName), notNullTagKeys );
return true;
}
bool QgsOSMDatabase::isExportsTableExists()
{
return runCountStatement("SELECT count(*) FROM sqlite_master WHERE type='table' "
"AND name='QGIS_OSM_EXPORTS_TABLES'") == 1
&& runCountStatement("SELECT count(*) FROM sqlite_master WHERE type='table' "
"AND name='QGIS_OSM_EXPORTS_COLUMNS'") == 1;
}
bool QgsOSMDatabase::createExportsTable()
{
if(isExportsTableExists())
return true;
QString sqlCreateTables = QString( "CREATE table IF NOT EXISTS QGIS_OSM_EXPORTS_TABLES "
" ( name TEXT PRIMARY KEY, type TEXT ); " );
char *errMsg = NULL;
int ret = sqlite3_exec( mDatabase, sqlCreateTables.toUtf8().constData(), NULL, NULL, &errMsg );
if ( ret != SQLITE_OK )
{
mError = "Unable to create QGIS_OSM_EXPORTS_TABLES:\n" + QString::fromUtf8( errMsg );
sqlite3_free( errMsg );
return false;
}
QString sqlCreateColumns = QString( "CREATE table IF NOT EXISTS QGIS_OSM_EXPORTS_COLUMNS "
"( id INTEGER PRIMARY KEY, layer TEXT, column TEXT, tag TEXT, isNotNll INTEGER, "
"FOREIGN KEY (layer) REFERENCES QGIS_OSM_EXPORTS_TABLES(name) ); " );
ret = sqlite3_exec( mDatabase, sqlCreateColumns.toUtf8().constData(), NULL, NULL, &errMsg );
if ( ret != SQLITE_OK )
{
mError = "Unable to create QGIS_OSM_EXPORTS_COLUMNS:\n" + QString::fromUtf8( errMsg );
sqlite3_free( errMsg );
return false;
}
return true;
}
QString QgsOSMDatabase::quotedIdentifier( QString id )
{
id.replace( "\"", "\"\"" );
return QString( "\"%1\"" ).arg( id );
}
QString QgsOSMDatabase::quotedValue( QString value )
{
if ( value.isNull() )
return "NULL";
value.replace( "'", "''" );
return QString( "'%1'" ).arg( value );
}
///////////////////////////////////
QgsOSMNodeIterator::QgsOSMNodeIterator( sqlite3* handle )
: mStmt( 0 )
{
const char* sql = "SELECT id,lon,lat FROM nodes";
if ( sqlite3_prepare_v2( handle, sql, -1, &mStmt, 0 ) != SQLITE_OK )
{
qDebug( "OSMNodeIterator: error prepare" );
}
}
QgsOSMNodeIterator::~QgsOSMNodeIterator()
{
close();
}
QgsOSMNode QgsOSMNodeIterator::next()
{
if ( !mStmt )
return QgsOSMNode();
if ( sqlite3_step( mStmt ) != SQLITE_ROW )
{
close();
return QgsOSMNode();
}
QgsOSMId id = sqlite3_column_int64( mStmt, 0 );
double lon = sqlite3_column_double( mStmt, 1 );
double lat = sqlite3_column_double( mStmt, 2 );
return QgsOSMNode( id, QgsPoint( lon, lat ) );
}
void QgsOSMNodeIterator::close()
{
if ( mStmt )
{
sqlite3_finalize( mStmt );
mStmt = 0;
}
}
///////////////////////////////////
QgsOSMWayIterator::QgsOSMWayIterator( sqlite3* handle )
: mStmt( 0 )
{
const char* sql = "SELECT id FROM ways";
if ( sqlite3_prepare_v2( handle, sql, -1, &mStmt, 0 ) != SQLITE_OK )
{
qDebug( "OSMWayIterator: error prepare" );
}
}
QgsOSMWayIterator::~QgsOSMWayIterator()
{
close();
}
QgsOSMWay QgsOSMWayIterator::next()
{
if ( !mStmt )
return QgsOSMWay();
if ( sqlite3_step( mStmt ) != SQLITE_ROW )
{
close();
return QgsOSMWay();
}
QgsOSMId id = sqlite3_column_int64( mStmt, 0 );
return QgsOSMWay( id, QList<QgsOSMId>() ); // TODO[MD]: ?
}
void QgsOSMWayIterator::close()
{
if ( mStmt )
{
sqlite3_finalize( mStmt );
mStmt = 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment