19 #include <QStringList> 20 #include <QXmlStreamReader> 24 : mXmlFileName( xmlFilename )
25 , mDbFileName( dbFilename )
26 , mDatabase( nullptr )
27 , mStmtInsertNode( nullptr )
28 , mStmtInsertNodeTag( nullptr )
29 , mStmtInsertWay( nullptr )
30 , mStmtInsertWayNode( nullptr )
31 , mStmtInsertWayTag( nullptr )
42 if ( !mInputFile.
open( QIODevice::ReadOnly ) )
44 mError =
QString(
"Cannot open input file: %1" ).
arg( mXmlFileName );
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",
nullptr,
nullptr,
nullptr );
68 Q_ASSERT( retX == SQLITE_OK );
75 while ( !xml.
atEnd() )
84 if ( xml.
name() ==
"osm" )
91 int retY = sqlite3_exec( mDatabase,
"COMMIT",
nullptr,
nullptr,
nullptr );
92 Q_ASSERT( retY == SQLITE_OK );
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],
nullptr,
nullptr,
nullptr );
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,
nullptr );
141 if ( ret == SQLITE_OK && rows == 1 && columns == 1 )
145 if ( parts.
size() >= 1 )
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],
nullptr,
nullptr, &errMsg ) != SQLITE_OK )
171 mError =
QString(
"Error executing SQL command:\n%1\nSQL:\n%2" )
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],
nullptr ) != SQLITE_OK )
202 const char* errMsg = sqlite3_errmsg( mDatabase );
203 mError =
QString(
"Error preparing SQL command:\n%1\nSQL:\n%2" )
218 sqlite3_finalize( stmt );
235 Q_ASSERT( !mStmtInsertNode );
248 while ( !xml.
atEnd() )
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" )
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 )
297 sqlite3_reset( mStmtInsertNode );
299 while ( !xml.
atEnd() )
308 if ( xml.
name() ==
"tag" )
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 )
335 sqlite3_reset( stmtInsertTag );
356 sqlite3_bind_int64( mStmtInsertWay, 1,
id );
358 if ( sqlite3_step( mStmtInsertWay ) != SQLITE_DONE )
363 sqlite3_reset( mStmtInsertWay );
367 while ( !xml.
atEnd() )
376 if ( xml.
name() ==
"nd" )
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 );
395 else if ( xml.
name() ==
"tag" )
QString errorString() const
QgsOSMXmlImport(const QString &xmlFileName=QString(), const QString &dbFileName=QString())
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
virtual qint64 pos() const
void setFileName(const QString &name)
QStringRef value(const QString &namespaceUri, const QString &name) const
double toDouble(bool *ok) const
static int sqlite3_close(sqlite3 *)
void raiseError(const QString &message)
void skipCurrentElement()
QString fromUtf8(const char *str, int size)
static int sqlite3_open_v2(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs)
const char * constData() const
void readWay(QXmlStreamReader &xml)
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
void readTag(bool way, QgsOSMId id, QXmlStreamReader &xml)
void progress(int percent)
virtual qint64 size() const
bool isEndDocument() const
bool isStartElement() const
QStringList split(const QString &sep, const QString &str, bool allowEmptyEntries)
QXmlStreamAttributes attributes() const
void readNode(QXmlStreamReader &xml)
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
qlonglong toLongLong(bool *ok, int base) const
void readRoot(QXmlStreamReader &xml)
bool isEndElement() const
void deleteStatement(sqlite3_stmt *&stmt)
QByteArray toUtf8() const