Used prepared statement rather than batch/offset for zxystream.

This commit is contained in:
Young Hahn
2015-01-16 12:54:59 -05:00
parent 18a9d50e2f
commit ea292f20c9
2 changed files with 21 additions and 58 deletions

View File

@@ -6,22 +6,13 @@ util.inherits(ZXYStream, stream.Readable);
// Readable stream of line-delimited z/x/y coordinates
// contained within the MBTiles `tiles` table/view.
//
// The `batch` option exists to allow tests to check that
// multiple calls to `_read` are handled properly. IRL the
// default offset of 1000 should be reasonably efficient
// and not worth messing with.
function ZXYStream(source, options) {
if (!source) throw new TypeError('MBTiles source required');
options = options || {};
if (options.batch !== undefined && typeof options.batch !== 'number')
throw new TypeError('options.batch must be a positive integer');
this.source = source;
this.batch = options.batch || 1000;
this.offset = 0;
this._afterGet = this._afterGet.bind(this);
stream.Readable.call(this);
}
@@ -38,15 +29,23 @@ ZXYStream.prototype._read = function() {
});
}
this.source._db.all('SELECT zoom_level AS z, tile_column AS x, tile_row AS y FROM ' + this.table + ' LIMIT ' + this.batch + ' OFFSET ' + this.offset, function(err, rows) {
if (err && err.code === 'SQLITE_ERROR' && /no such table/.test(err.message)) return stream.push(null);
if (err) return stream.emit('error', err);
if (!rows.length) return stream.push(null);
stream.offset += stream.batch;
var chunk = '';
for (var i = 0; i < rows.length; i++) chunk += toLine(rows[i]);
stream.push(chunk);
});
// Prepare sql statement
if (!stream.statement) {
stream.statement = this.source._db.prepare('SELECT zoom_level AS z, tile_column AS x, tile_row AS y FROM ' + this.table, function(err) {
if (err && err.code === 'SQLITE_ERROR' && /no such table/.test(err.message)) return stream.push(null);
return stream._read();
});
return;
}
stream.statement.get(stream._afterGet);
};
ZXYStream.prototype._afterGet = function(err, row) {
if (err && err.code === 'SQLITE_ERROR' && /no such table/.test(err.message)) return this.push(null);
if (err) return this.emit('error', err);
if (!row) return this.push(null);
this.push(toLine(row));
};
function toLine(row) {