78 lines
2.3 KiB
JavaScript
78 lines
2.3 KiB
JavaScript
var stream = require('stream');
|
|
var util = require('util');
|
|
|
|
module.exports = ZXYStream;
|
|
util.inherits(ZXYStream, stream.Readable);
|
|
|
|
// Readable stream of line-delimited z/x/y coordinates
|
|
// contained within the MBTiles `tiles` table/view.
|
|
function ZXYStream(source, options) {
|
|
if (!source) throw new TypeError('MBTiles source required');
|
|
|
|
options = options || {};
|
|
|
|
this.source = source;
|
|
this.batch = options.batch || 1000;
|
|
|
|
stream.Readable.call(this);
|
|
}
|
|
|
|
ZXYStream.prototype._read = function() {
|
|
var stream = this;
|
|
|
|
// Check for the existence of a map table that is indexed.
|
|
if (!stream.table) {
|
|
return this.source._db.get("select count(1) as count from sqlite_master where type = 'index' and tbl_name = 'map';", function(err, row) {
|
|
if (err) return stream.emit('error', err);
|
|
stream.table = row.count >= 1 ? 'map' : 'tiles';
|
|
return stream._read();
|
|
});
|
|
}
|
|
|
|
// Prepare sql statement
|
|
if (!stream.statement) {
|
|
var query = 'SELECT zoom_level AS z, tile_column AS x, tile_row AS y FROM ' + this.table;
|
|
if (this.table === 'map') query += ' WHERE tile_id is not null';
|
|
|
|
stream.statement = this.source._db.prepare(query, function(err) {
|
|
if (err && err.code === 'SQLITE_ERROR' && /no such table/.test(err.message)) return stream.push(null);
|
|
return stream._read();
|
|
});
|
|
return;
|
|
}
|
|
|
|
var lines = '';
|
|
var error;
|
|
var remaining = stream.batch;
|
|
for (var i = 0; i < stream.batch; i++) stream.statement.get(afterGet);
|
|
|
|
function afterGet(err, row) {
|
|
if (err && err.code === 'SQLITE_ERROR' && /no such table/.test(err.message)) {
|
|
// no-op
|
|
} else if (err) {
|
|
error = err;
|
|
} else if (!row) {
|
|
// no-op
|
|
} else {
|
|
lines += toLine(row);
|
|
}
|
|
if (!--remaining) {
|
|
if (error) {
|
|
stream.emit('error', error);
|
|
} else {
|
|
if (lines) stream.push(lines);
|
|
else {
|
|
stream.statement.finalize();
|
|
stream.push(null);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
function toLine(row) {
|
|
// Flip Y coordinate because MBTiles files are TMS.
|
|
var y = row.y = (1 << row.z) - 1 - row.y;
|
|
return row.z + '/' + row.x + '/' + y + '\n';
|
|
}
|