From 61cec80d4de39a1d7fdfdfc0374331124e9cceba Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Thu, 9 Jan 2014 17:24:48 +0100 Subject: [PATCH] Fix use of "SELECT .. INTO" with windowing params Includes testcase. Closes #127 --- NEWS.md | 5 ++++ app/models/psql.js | 13 ++++++++- test/acceptance/app.test.js | 56 +++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index d595564e..1f00e810 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,11 @@ 1.8.1 - 2013-12-DD ------------------ +Bug fixes: + + * Fix use of "SELECT .. INTO" with windowing params (#127) + + 1.8.0 - 2013-12-18 ------------------ diff --git a/app/models/psql.js b/app/models/psql.js index 53667518..633f948f 100644 --- a/app/models/psql.js +++ b/app/models/psql.js @@ -317,7 +317,18 @@ console.log("rem: " + rem); } - if ( sql.match(/^\s*SELECT\s/i) ) { + var re_SELECT = RegExp(/^\s*SELECT\s/i); + var re_INTO = RegExp(/\sINTO\s+([^\s]+|"([^"]|"")*")\s*$/i); + + //console.log("SQL " + sql); + //console.log(" does " + ( sql.match(re_SELECT) ? '' : 'not ' ) + "match re_SELECT " + re_SELECT); + //console.log(" does " + ( sql.match(re_INTO) ? '' : 'not ' ) + "match re_INTO " + re_INTO); + + if ( + sql.match(re_SELECT) && + ! sql.match(re_INTO) + ) + { return cte + "SELECT * FROM (" + sql + ") AS cdbq_1 LIMIT " + limit + " OFFSET " + offset; } diff --git a/test/acceptance/app.test.js b/test/acceptance/app.test.js index dd49b0bb..65592345 100644 --- a/test/acceptance/app.test.js +++ b/test/acceptance/app.test.js @@ -497,6 +497,62 @@ test('CREATE TABLE with GET and auth', function(done){ }); }); +// See http://github.com/CartoDB/CartoDB-SQL-API/issues/127 +test('SELECT INTO with paging ', function(done){ + var esc_tabname = 'test ""select into""'; // escaped ident + Step( + function select_into() { + var next = this; + assert.response(app, { + url: "/api/v1/sql?" + querystring.stringify({ + q: 'SELECT generate_series(1,10) InTO "' + esc_tabname + '"', + rows_per_page: 1, page: 1, + api_key: 1234 + }), + headers: {host: 'vizzuality.cartodb.com'}, + method: 'GET' + },{}, function(res) { next(null, res); }); + }, + function check_res_test_fake_into_1(err, res) { + if ( err ) throw err; + assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); + var next = this; + assert.response(app, { + url: "/api/v1/sql?" + querystring.stringify({ + q: 'SELECT \' INTO "c"\' FROM "' + esc_tabname + '"', + rows_per_page: 1, page: 1, + api_key: 1234 + }), + headers: {host: 'vizzuality.cartodb.com'}, + method: 'GET' + },{}, function(res) { next(null, res); }); + }, + function check_res_drop_table(err, res) { + if ( err ) throw err; + assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); + var out = JSON.parse(res.body); + assert.equal(out.total_rows, 1); // windowing works + var next = this; + assert.response(app, { + url: "/api/v1/sql?" + querystring.stringify({ + q: 'DROP TABLE "' + esc_tabname + '"', + api_key: 1234 + }), + headers: {host: 'vizzuality.cartodb.com'}, + method: 'GET' + },{}, function(res) { next(null, res); }); + }, + function check_drop(err, res) { + if ( err ) throw err; + assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); + return null; + }, + function finish(err) { + done(err) + } + ); +}); + // Test effects of COPY // See https://github.com/Vizzuality/cartodb-management/issues/1502 test('COPY TABLE with GET and auth', function(done){