18 #include <spatialite.h>
20 #include <QStringList>
21 #include <QXmlStreamReader>
25 : mXmlFileName( xmlFilename )
26 , mDbFileName( dbFilename )
28 , mStmtInsertNode( 0 )
29 , mStmtInsertNodeTag( 0 )
31 , mStmtInsertWayNode( 0 )
32 , mStmtInsertWayTag( 0 )
42 mInputFile.setFileName( mXmlFileName );
43 if ( !mInputFile.open( QIODevice::ReadOnly ) )
45 mError = QString(
"Cannot open input file: %1" ).arg( mXmlFileName );
51 if ( QFile::exists( mDbFileName ) )
53 if ( !QFile( mDbFileName ).
remove() )
55 mError = QString(
"Database file cannot be overwritten: %1" ).arg( mDbFileName );
69 qDebug(
"starting import" );
71 int retX = sqlite3_exec( mDatabase,
"BEGIN", NULL, NULL, 0 );
72 Q_ASSERT( retX == SQLITE_OK );
77 QXmlStreamReader xml( &mInputFile );
79 while ( !xml.atEnd() )
83 if ( xml.isEndDocument() )
86 if ( xml.isStartElement() )
88 if ( xml.name() ==
"osm" )
91 xml.raiseError(
"Invalid root tag" );
95 int retY = sqlite3_exec( mDatabase,
"COMMIT", NULL, NULL, 0 );
96 Q_ASSERT( retY == SQLITE_OK );
101 if ( xml.hasError() )
103 mError = QString(
"XML error: %1" ).arg( xml.errorString() );
115 const char* sqlIndexes[] =
117 "CREATE INDEX nodes_tags_idx ON nodes_tags(id)",
118 "CREATE INDEX ways_tags_idx ON ways_tags(id)",
119 "CREATE INDEX ways_nodes_way ON ways_nodes(way_id)"
121 int count =
sizeof( sqlIndexes ) /
sizeof(
const char* );
122 for (
int i = 0; i < count; ++i )
124 int ret = sqlite3_exec( mDatabase, sqlIndexes[i], 0, 0, 0 );
125 if ( ret != SQLITE_OK )
127 mError =
"Error creating indexes!";
140 if ( sqlite3_open_v2( mDbFileName.toUtf8().data(), &mDatabase, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0 ) != SQLITE_OK )
143 bool above41 =
false;
144 int ret = sqlite3_get_table( mDatabase,
"select spatialite_version()", &results, &rows, &columns, NULL );
145 if ( ret == SQLITE_OK && rows == 1 && columns == 1 )
147 QString version = QString::fromUtf8( results[1] );
148 QStringList parts = version.split(
" ", QString::SkipEmptyParts );
149 if ( parts.size() >= 1 )
151 QStringList verparts = parts[0].split(
".", QString::SkipEmptyParts );
152 above41 = verparts.size() >= 2 && ( verparts[0].toInt() > 4 || ( verparts[0].toInt() == 4 && verparts[1].toInt() >= 1 ) );
155 sqlite3_free_table( results );
157 const char* sqlInitStatements[] =
159 "PRAGMA cache_size = 100000",
160 "PRAGMA synchronous = OFF",
161 above41 ?
"SELECT InitSpatialMetadata(1)" :
"SELECT InitSpatialMetadata()",
162 "CREATE TABLE nodes ( id INTEGER PRIMARY KEY, lat REAL, lon REAL )",
163 "CREATE TABLE nodes_tags ( id INTEGER, k TEXT, v TEXT )",
164 "CREATE TABLE ways ( id INTEGER PRIMARY KEY )",
165 "CREATE TABLE ways_nodes ( way_id INTEGER, node_id INTEGER, way_pos INTEGER )",
166 "CREATE TABLE ways_tags ( id INTEGER, k TEXT, v TEXT )",
169 int initCount =
sizeof( sqlInitStatements ) /
sizeof(
const char* );
170 for (
int i = 0; i < initCount; ++i )
173 if ( sqlite3_exec( mDatabase, sqlInitStatements[i], 0, 0, &errMsg ) != SQLITE_OK )
175 mError = QString(
"Error executing SQL command:\n%1\nSQL:\n%2" )
176 .arg( QString::fromUtf8( errMsg ) ).arg( QString::fromUtf8( sqlInitStatements[i] ) );
177 sqlite3_free( errMsg );
183 const char* sqlInsertStatements[] =
185 "INSERT INTO nodes ( id, lat, lon ) VALUES (?,?,?)",
186 "INSERT INTO nodes_tags ( id, k, v ) VALUES (?,?,?)",
187 "INSERT INTO ways ( id ) VALUES (?)",
188 "INSERT INTO ways_nodes ( way_id, node_id, way_pos ) VALUES (?,?,?)",
189 "INSERT INTO ways_tags ( id, k, v ) VALUES (?,?,?)"
191 sqlite3_stmt** sqliteInsertStatements[] =
199 Q_ASSERT(
sizeof( sqlInsertStatements ) /
sizeof(
const char* ) ==
sizeof( sqliteInsertStatements ) /
sizeof( sqlite3_stmt** ) );
200 int insertCount =
sizeof( sqlInsertStatements ) /
sizeof(
const char* );
202 for (
int i = 0; i < insertCount; ++i )
204 if ( sqlite3_prepare_v2( mDatabase, sqlInsertStatements[i], -1, sqliteInsertStatements[i], 0 ) != SQLITE_OK )
206 const char* errMsg = sqlite3_errmsg( mDatabase );
207 mError = QString(
"Error preparing SQL command:\n%1\nSQL:\n%2" )
208 .arg( QString::fromUtf8( errMsg ) ).arg( QString::fromUtf8( sqlInsertStatements[i] ) );
222 sqlite3_finalize( stmt );
239 Q_ASSERT( mStmtInsertNode == 0 );
241 sqlite3_close( mDatabase );
252 while ( !xml.atEnd() )
256 if ( xml.isEndElement() )
259 if ( xml.isStartElement() )
263 int new_percent = 100 * mInputFile.pos() / mInputFile.size();
264 if ( new_percent > percent )
267 percent = new_percent;
272 if ( xml.name() ==
"node" )
274 else if ( xml.name() ==
"way" )
277 xml.skipCurrentElement();
286 QXmlStreamAttributes attrs = xml.attributes();
287 QgsOSMId id = attrs.value(
"id" ).toString().toLongLong();
288 double lat = attrs.value(
"lat" ).toString().toDouble();
289 double lon = attrs.value(
"lon" ).toString().toDouble();
292 sqlite3_bind_int64( mStmtInsertNode, 1,
id );
293 sqlite3_bind_double( mStmtInsertNode, 2, lat );
294 sqlite3_bind_double( mStmtInsertNode, 3, lon );
296 if ( sqlite3_step( mStmtInsertNode ) != SQLITE_DONE )
298 xml.raiseError( QString(
"Storing node %1 failed." ).arg(
id ) );
301 sqlite3_reset( mStmtInsertNode );
303 while ( !xml.atEnd() )
307 if ( xml.isEndElement() )
310 if ( xml.isStartElement() )
312 if ( xml.name() ==
"tag" )
315 xml.raiseError(
"Invalid tag in <node>" );
322 QXmlStreamAttributes attrs = xml.attributes();
323 QByteArray k = attrs.value(
"k" ).toString().toUtf8();
324 QByteArray v = attrs.value(
"v" ).toString().toUtf8();
325 xml.skipCurrentElement();
327 sqlite3_stmt* stmtInsertTag = way ? mStmtInsertWayTag : mStmtInsertNodeTag;
329 sqlite3_bind_int64( stmtInsertTag, 1,
id );
330 sqlite3_bind_text( stmtInsertTag, 2, k.constData(), -1, SQLITE_STATIC );
331 sqlite3_bind_text( stmtInsertTag, 3, v.constData(), -1, SQLITE_STATIC );
333 int res = sqlite3_step( stmtInsertTag );
334 if ( res != SQLITE_DONE )
336 xml.raiseError( QString(
"Storing tag failed [%1]" ).arg( res ) );
339 sqlite3_reset( stmtInsertTag );
356 QXmlStreamAttributes attrs = xml.attributes();
357 QgsOSMId id = attrs.value(
"id" ).toString().toLongLong();
360 sqlite3_bind_int64( mStmtInsertWay, 1,
id );
362 if ( sqlite3_step( mStmtInsertWay ) != SQLITE_DONE )
364 xml.raiseError( QString(
"Storing way %1 failed." ).arg(
id ) );
367 sqlite3_reset( mStmtInsertWay );
371 while ( !xml.atEnd() )
375 if ( xml.isEndElement() )
378 if ( xml.isStartElement() )
380 if ( xml.name() ==
"nd" )
382 QgsOSMId node_id = xml.attributes().value(
"ref" ).toString().toLongLong();
384 sqlite3_bind_int64( mStmtInsertWayNode, 1,
id );
385 sqlite3_bind_int64( mStmtInsertWayNode, 2, node_id );
386 sqlite3_bind_int( mStmtInsertWayNode, 3, way_pos );
388 if ( sqlite3_step( mStmtInsertWayNode ) != SQLITE_DONE )
390 xml.raiseError( QString(
"Storing ways_nodes %1 - %2 failed." ).arg(
id ).arg( node_id ) );
393 sqlite3_reset( mStmtInsertWayNode );
397 xml.skipCurrentElement();
399 else if ( xml.name() ==
"tag" )
402 xml.skipCurrentElement();