19 #include <QStringList> 20 #include <QXmlStreamReader> 24 : mXmlFileName( xmlFilename )
25 , mDbFileName( dbFilename )
27 , mStmtInsertNode( 0 )
28 , mStmtInsertNodeTag( 0 )
30 , mStmtInsertWayNode( 0 )
31 , mStmtInsertWayTag( 0 )
41 mInputFile.setFileName( mXmlFileName );
42 if ( !mInputFile.open( QIODevice::ReadOnly ) )
44 mError = QString(
"Cannot open input file: %1" ).arg( mXmlFileName );
50 if ( QFile::exists( mDbFileName ) )
52 if ( !QFile( mDbFileName ).
remove() )
54 mError = QString(
"Database file cannot be overwritten: %1" ).arg( mDbFileName );
65 qDebug(
"starting import" );
67 int retX = sqlite3_exec( mDatabase,
"BEGIN", NULL, NULL, 0 );
68 Q_ASSERT( retX == SQLITE_OK );
73 QXmlStreamReader xml( &mInputFile );
75 while ( !xml.atEnd() )
79 if ( xml.isEndDocument() )
82 if ( xml.isStartElement() )
84 if ( xml.name() ==
"osm" )
87 xml.raiseError(
"Invalid root tag" );
91 int retY = sqlite3_exec( mDatabase,
"COMMIT", NULL, NULL, 0 );
92 Q_ASSERT( retY == SQLITE_OK );
99 mError = QString(
"XML error: %1" ).arg( xml.errorString() );
111 const char* sqlIndexes[] =
113 "CREATE INDEX nodes_tags_idx ON nodes_tags(id)",
114 "CREATE INDEX ways_tags_idx ON ways_tags(id)",
115 "CREATE INDEX ways_nodes_way ON ways_nodes(way_id)" 117 int count =
sizeof( sqlIndexes ) /
sizeof(
const char* );
118 for (
int i = 0; i < count; ++i )
120 int ret = sqlite3_exec( mDatabase, sqlIndexes[i], 0, 0, 0 );
121 if ( ret != SQLITE_OK )
123 mError =
"Error creating indexes!";
139 bool above41 =
false;
140 int ret = sqlite3_get_table( mDatabase,
"select spatialite_version()", &results, &rows, &columns, NULL );
141 if ( ret == SQLITE_OK && rows == 1 && columns == 1 )
143 QString version = QString::fromUtf8( results[1] );
144 QStringList parts = version.split(
" ", QString::SkipEmptyParts );
145 if ( parts.size() >= 1 )
147 QStringList verparts = parts[0].split(
".", QString::SkipEmptyParts );
148 above41 = verparts.size() >= 2 && ( verparts[0].toInt() > 4 || ( verparts[0].toInt() == 4 && verparts[1].toInt() >= 1 ) );
151 sqlite3_free_table( results );
153 const char* sqlInitStatements[] =
155 "PRAGMA cache_size = 100000",
156 "PRAGMA synchronous = OFF",
157 above41 ?
"SELECT InitSpatialMetadata(1)" :
"SELECT InitSpatialMetadata()",
158 "CREATE TABLE nodes ( id INTEGER PRIMARY KEY, lat REAL, lon REAL )",
159 "CREATE TABLE nodes_tags ( id INTEGER, k TEXT, v TEXT )",
160 "CREATE TABLE ways ( id INTEGER PRIMARY KEY )",
161 "CREATE TABLE ways_nodes ( way_id INTEGER, node_id INTEGER, way_pos INTEGER )",
162 "CREATE TABLE ways_tags ( id INTEGER, k TEXT, v TEXT )",
165 int initCount =
sizeof( sqlInitStatements ) /
sizeof(
const char* );
166 for (
int i = 0; i < initCount; ++i )
169 if ( sqlite3_exec( mDatabase, sqlInitStatements[i], 0, 0, &errMsg ) != SQLITE_OK )
171 mError = QString(
"Error executing SQL command:\n%1\nSQL:\n%2" )
172 .arg( QString::fromUtf8( errMsg ) ).arg( QString::fromUtf8( sqlInitStatements[i] ) );
173 sqlite3_free( errMsg );
179 const char* sqlInsertStatements[] =
181 "INSERT INTO nodes ( id, lat, lon ) VALUES (?,?,?)",
182 "INSERT INTO nodes_tags ( id, k, v ) VALUES (?,?,?)",
183 "INSERT INTO ways ( id ) VALUES (?)",
184 "INSERT INTO ways_nodes ( way_id, node_id, way_pos ) VALUES (?,?,?)",
185 "INSERT INTO ways_tags ( id, k, v ) VALUES (?,?,?)" 187 sqlite3_stmt** sqliteInsertStatements[] =
195 Q_ASSERT(
sizeof( sqlInsertStatements ) /
sizeof(
const char* ) ==
sizeof( sqliteInsertStatements ) /
sizeof( sqlite3_stmt** ) );
196 int insertCount =
sizeof( sqlInsertStatements ) /
sizeof(
const char* );
198 for (
int i = 0; i < insertCount; ++i )
200 if ( sqlite3_prepare_v2( mDatabase, sqlInsertStatements[i], -1, sqliteInsertStatements[i], 0 ) != SQLITE_OK )
202 const char* errMsg = sqlite3_errmsg( mDatabase );
203 mError = QString(
"Error preparing SQL command:\n%1\nSQL:\n%2" )
204 .arg( QString::fromUtf8( errMsg ) ).arg( QString::fromUtf8( sqlInsertStatements[i] ) );
218 sqlite3_finalize( stmt );
235 Q_ASSERT( mStmtInsertNode == 0 );
248 while ( !xml.atEnd() )
252 if ( xml.isEndElement() )
255 if ( xml.isStartElement() )
259 int new_percent = 100 * mInputFile.pos() / mInputFile.size();
260 if ( new_percent > percent )
263 percent = new_percent;
268 if ( xml.name() ==
"node" )
270 else if ( xml.name() ==
"way" )
273 xml.skipCurrentElement();
282 QXmlStreamAttributes attrs = xml.attributes();
283 QgsOSMId id = attrs.value(
"id" ).toString().toLongLong();
284 double lat = attrs.value(
"lat" ).toString().toDouble();
285 double lon = attrs.value(
"lon" ).toString().toDouble();
288 sqlite3_bind_int64( mStmtInsertNode, 1,
id );
289 sqlite3_bind_double( mStmtInsertNode, 2, lat );
290 sqlite3_bind_double( mStmtInsertNode, 3, lon );
292 if ( sqlite3_step( mStmtInsertNode ) != SQLITE_DONE )
294 xml.raiseError( QString(
"Storing node %1 failed." ).arg(
id ) );
297 sqlite3_reset( mStmtInsertNode );
299 while ( !xml.atEnd() )
303 if ( xml.isEndElement() )
306 if ( xml.isStartElement() )
308 if ( xml.name() ==
"tag" )
311 xml.raiseError(
"Invalid tag in <node>" );
318 QXmlStreamAttributes attrs = xml.attributes();
319 QByteArray k = attrs.value(
"k" ).toString().toUtf8();
320 QByteArray v = attrs.value(
"v" ).toString().toUtf8();
321 xml.skipCurrentElement();
323 sqlite3_stmt* stmtInsertTag = way ? mStmtInsertWayTag : mStmtInsertNodeTag;
325 sqlite3_bind_int64( stmtInsertTag, 1,
id );
326 sqlite3_bind_text( stmtInsertTag, 2, k.constData(), -1, SQLITE_STATIC );
327 sqlite3_bind_text( stmtInsertTag, 3, v.constData(), -1, SQLITE_STATIC );
329 int res = sqlite3_step( stmtInsertTag );
330 if ( res != SQLITE_DONE )
332 xml.raiseError( QString(
"Storing tag failed [%1]" ).arg( res ) );
335 sqlite3_reset( stmtInsertTag );
352 QXmlStreamAttributes attrs = xml.attributes();
353 QgsOSMId id = attrs.value(
"id" ).toString().toLongLong();
356 sqlite3_bind_int64( mStmtInsertWay, 1,
id );
358 if ( sqlite3_step( mStmtInsertWay ) != SQLITE_DONE )
360 xml.raiseError( QString(
"Storing way %1 failed." ).arg(
id ) );
363 sqlite3_reset( mStmtInsertWay );
367 while ( !xml.atEnd() )
371 if ( xml.isEndElement() )
374 if ( xml.isStartElement() )
376 if ( xml.name() ==
"nd" )
378 QgsOSMId node_id = xml.attributes().value(
"ref" ).toString().toLongLong();
380 sqlite3_bind_int64( mStmtInsertWayNode, 1,
id );
381 sqlite3_bind_int64( mStmtInsertWayNode, 2, node_id );
382 sqlite3_bind_int( mStmtInsertWayNode, 3, way_pos );
384 if ( sqlite3_step( mStmtInsertWayNode ) != SQLITE_DONE )
386 xml.raiseError( QString(
"Storing ways_nodes %1 - %2 failed." ).arg(
id ).arg( node_id ) );
389 sqlite3_reset( mStmtInsertWayNode );
393 xml.skipCurrentElement();
395 else if ( xml.name() ==
"tag" )
398 xml.skipCurrentElement();
QgsOSMXmlImport(const QString &xmlFileName=QString(), const QString &dbFileName=QString())
static int sqlite3_close(sqlite3 *)
static int sqlite3_open_v2(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs)
void readWay(QXmlStreamReader &xml)
void readTag(bool way, QgsOSMId id, QXmlStreamReader &xml)
void progress(int percent)
void readNode(QXmlStreamReader &xml)
void readRoot(QXmlStreamReader &xml)
void deleteStatement(sqlite3_stmt *&stmt)