|
|
|
@ -95,21 +95,15 @@ OgrFormat.prototype.toOGR = function (options, outFormat, outFilename, callback)
|
|
|
|
|
step(
|
|
|
|
|
|
|
|
|
|
function fetchColumns () {
|
|
|
|
|
logger.info({ custom: true }, 'Getting dataset columns');
|
|
|
|
|
|
|
|
|
|
var colsql = 'SELECT * FROM (' + sql + ') as _cartodbsqlapi LIMIT 0';
|
|
|
|
|
pg = new PSQL(dbopts);
|
|
|
|
|
pg.query(colsql, this);
|
|
|
|
|
|
|
|
|
|
logger.info({ custom: true, colsql: colsql }, 'Dataset columns query done');
|
|
|
|
|
},
|
|
|
|
|
function findSRS (err, result) {
|
|
|
|
|
if (err) {
|
|
|
|
|
throw err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logger.info({ custom: true }, 'FindSRS');
|
|
|
|
|
|
|
|
|
|
var needSRS = that._needSRS;
|
|
|
|
|
|
|
|
|
|
columns = result.fields
|
|
|
|
@ -156,8 +150,6 @@ OgrFormat.prototype.toOGR = function (options, outFormat, outFilename, callback)
|
|
|
|
|
throw err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logger.info({ custom: true }, 'Generating ogr2ogr parameters');
|
|
|
|
|
|
|
|
|
|
var next = this;
|
|
|
|
|
|
|
|
|
|
var ogrsql = 'SELECT ' + columns.join(',') + ' FROM (' + sql + ') as _cartodbsqlapi';
|
|
|
|
@ -187,8 +179,6 @@ OgrFormat.prototype.toOGR = function (options, outFormat, outFilename, callback)
|
|
|
|
|
|
|
|
|
|
ogrargs.push('-nln', outLayername);
|
|
|
|
|
|
|
|
|
|
logger.info({ custom: true }, 'Executing ogr2ogr command');
|
|
|
|
|
|
|
|
|
|
// TODO: research if `exec` could fit better than `spawn`
|
|
|
|
|
var child = spawn(ogr2ogr, ogrargs);
|
|
|
|
|
|
|
|
|
@ -238,8 +228,6 @@ OgrFormat.prototype.toOGR = function (options, outFormat, outFilename, callback)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
OgrFormat.prototype.toOGR_SingleFile = function (options, fmt, callback) {
|
|
|
|
|
logger.info({ custom: true }, 'Generating filename');
|
|
|
|
|
|
|
|
|
|
var dbname = options.dbopts.dbname;
|
|
|
|
|
var userId = options.dbopts.user;
|
|
|
|
|
var gcol = options.gcol;
|
|
|
|
@ -248,8 +236,6 @@ OgrFormat.prototype.toOGR_SingleFile = function (options, fmt, callback) {
|
|
|
|
|
var ext = this._fileExtension;
|
|
|
|
|
var layername = options.filename;
|
|
|
|
|
|
|
|
|
|
logger.info({ custom: true }, 'Generating filename parameters');
|
|
|
|
|
|
|
|
|
|
var tmpdir = global.settings.tmpDir || '/tmp';
|
|
|
|
|
var reqKey = this.limitPathname([
|
|
|
|
|
fmt,
|
|
|
|
@ -262,8 +248,6 @@ OgrFormat.prototype.toOGR_SingleFile = function (options, fmt, callback) {
|
|
|
|
|
var outdirpath = tmpdir + '/sqlapi-' + process.pid + '-' + reqKey;
|
|
|
|
|
var dumpfile = outdirpath + ':cartodb-query.' + ext;
|
|
|
|
|
|
|
|
|
|
logger.info({ custom: true, dumpfile: dumpfile }, 'File name generated');
|
|
|
|
|
|
|
|
|
|
// TODO: following tests:
|
|
|
|
|
// - fetch query with no "the_geom" column
|
|
|
|
|
this.toOGR(options, fmt, dumpfile, callback);
|
|
|
|
@ -271,20 +255,17 @@ OgrFormat.prototype.toOGR_SingleFile = function (options, fmt, callback) {
|
|
|
|
|
|
|
|
|
|
OgrFormat.prototype.sendResponse = function (opts, callback) {
|
|
|
|
|
// var next = callback;
|
|
|
|
|
|
|
|
|
|
logger.info({ custom: true }, 'Format sendResponse');
|
|
|
|
|
var reqKey = this.getKey(opts);
|
|
|
|
|
logger.info({ custom: true }, 'Format getKey');
|
|
|
|
|
var qElem = new ExportRequest(opts.sink, callback, opts.beforeSink);
|
|
|
|
|
logger.info({ custom: true }, 'Format qElem');
|
|
|
|
|
var baking = bakingExports[reqKey];
|
|
|
|
|
logger.info({ custom: true }, 'Format baking');
|
|
|
|
|
|
|
|
|
|
if (baking) {
|
|
|
|
|
logger.info({ custom: true, reqKey: reqKey }, 'Baking!');
|
|
|
|
|
baking.req.push(qElem);
|
|
|
|
|
} else {
|
|
|
|
|
logger.info({ custom: true, reqKey: reqKey }, 'Not baking!');
|
|
|
|
|
|
|
|
|
|
baking = bakingExports[reqKey] = { req: [qElem] };
|
|
|
|
|
logger.info({ custom: true }, 'Format generate');
|
|
|
|
|
this.generate(opts, function (err, dumpfile) {
|
|
|
|
|
if (opts.profiler) {
|
|
|
|
|
opts.profiler.done('generate');
|
|
|
|
@ -292,6 +273,7 @@ OgrFormat.prototype.sendResponse = function (opts, callback) {
|
|
|
|
|
step(
|
|
|
|
|
function sendResults () {
|
|
|
|
|
var nextPipe = function (finish) {
|
|
|
|
|
logger.info({ custom: true, size: baking.req.length }, 'Sending responses');
|
|
|
|
|
var r = baking.req.shift();
|
|
|
|
|
if (!r) { finish(null); return; }
|
|
|
|
|
r.sendFile(err, dumpfile, function () {
|
|
|
|
@ -309,12 +291,17 @@ OgrFormat.prototype.sendResponse = function (opts, callback) {
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
function cleanup (/* err */) {
|
|
|
|
|
logger.info({ custom: true, reqKey: reqKey, size: bakingExports[reqKey].req.length }, 'Deleting key');
|
|
|
|
|
delete bakingExports[reqKey];
|
|
|
|
|
|
|
|
|
|
// unlink dump file (sync to avoid race condition)
|
|
|
|
|
console.log('removing', dumpfile);
|
|
|
|
|
try { fs.unlinkSync(dumpfile); } catch (e) {
|
|
|
|
|
try {
|
|
|
|
|
logger.info({ custom: true }, 'Unlink dumpfile');
|
|
|
|
|
fs.unlinkSync(dumpfile);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
if (e.code !== 'ENOENT') {
|
|
|
|
|
logger.info({ custom: true }, 'Error removing dumpfile');
|
|
|
|
|
console.log('Could not unlink dumpfile ' + dumpfile + ': ' + e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -325,7 +312,6 @@ OgrFormat.prototype.sendResponse = function (opts, callback) {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function ExportRequest (ostream, callback, beforeSink) {
|
|
|
|
|
logger.info({ custom: true }, 'Creating ExportRequest');
|
|
|
|
|
this.cb = callback;
|
|
|
|
|
this.beforeSink = beforeSink;
|
|
|
|
|
this.ostream = ostream;
|
|
|
|
@ -334,8 +320,6 @@ function ExportRequest (ostream, callback, beforeSink) {
|
|
|
|
|
|
|
|
|
|
var that = this;
|
|
|
|
|
|
|
|
|
|
logger.info({ custom: true }, 'Keep creating ExportRequest');
|
|
|
|
|
|
|
|
|
|
this.ostream.on('close', function () {
|
|
|
|
|
that.canceled = true;
|
|
|
|
|
if (that.istream) {
|
|
|
|
|