From 8ef749b2aba592367bf16db39a25af80a45daf1d Mon Sep 17 00:00:00 2001 From: Biju Nakarmi Date: Tue, 10 Apr 2018 13:01:58 +0545 Subject: [PATCH] [UNTP-204]fix on Potential logical problem in yearly projects calculation - [x] query to fetch stats are modified - [x] UNCDF id updated to XM-DAC-41111 --- ctrack/art/un_logos/41111_old.png | Bin 7019 -> 0 bytes ctrack/art/un_logos/XM-DAC-41111.png | Bin 0 -> 8453 bytes ctrack/js/view_list_activities.js | 279 ++--- ctrack/js/view_stats.js | 260 +++-- dportal/js/undg.js | 521 +++++---- dportal/source/index.^.html | 2 +- dstore/js/query.js | 1526 +++++++++++++------------- dstore/json/iati_codes.json | 136 ++- dstore/json/un_agencies_data.json | 177 +-- 9 files changed, 1513 insertions(+), 1388 deletions(-) delete mode 100755 ctrack/art/un_logos/41111_old.png create mode 100644 ctrack/art/un_logos/XM-DAC-41111.png diff --git a/ctrack/art/un_logos/41111_old.png b/ctrack/art/un_logos/41111_old.png deleted file mode 100755 index 24fdec1542036c700bdff06c13907fabbc325abd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7019 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 JPDHLkV1kTZtqK4D diff --git a/ctrack/art/un_logos/XM-DAC-41111.png b/ctrack/art/un_logos/XM-DAC-41111.png new file mode 100644 index 0000000000000000000000000000000000000000..8600ddbbc27cebd60c1626c7d1e3c10f83b72d71 GIT binary patch literal 8453 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 nNhjuD@3pz79fyCLx_100){d.pct=100;} - } - a.push(d); - s.push( plate.replace(args.plate || "{list_activities_data}",d) ); - } - ctrack.chunk(args.chunk || "list_activities_datas",s.join("")); - ctrack.chunk("total",data.rows.length); - - - var cc=[]; - cc[0]=["aid","title","reporting","commitment","spend","currency"]; - a.forEach(function(v){ - cc[cc.length]=[v.aid,v.title,v.reporting,v.commitment,v.spend,v.currency]; - }); - ctrack.chunk((args.chunk || "list_activities_datas")+"_csv","data:text/csv;charset=UTF-8,"+encodeURIComponent(csvw.arrayToCSV(cc))); - - } - if(args.callback){args.callback(data);} - ctrack.display(); - }); -} +view_list_activities.ajax = function(args) { + args = args || {}; + args.zerodata = args.zerodata || "{alert_no_data1}"; + + var dat = { + from: "act", + limit: args.limit || -1, + select: + "title,aid,funder_ref," + + ctrack.convert_str("commitment") + + "," + + ctrack.convert_str("spend") + + ",reporting,reporting_ref,sector_ref,day_start,day_end", + orderby: "4-", + groupby: "aid" + // "country_code":(args.country || ctrack.args.country_select), + // "reporting_ref":(args.publisher || ctrack.args.publisher_select), + // "title_like":(args.search || ctrack.args.search), + // "sector_code":(args.sector_code || ctrack.args.sector_code_select), + // "sector_group":(args.sector_group || ctrack.args.sector_group_select), + // "funder_ref":(args.funder_ref || ctrack.args.funder_ref_select), + // "day_start_lteq":(args.date_max || ctrack.args.date_max), + // "day_end_gteq":(args.date_min || ctrack.args.date_min), + }; + // for(var n in ctrack.hash) { dat[n]=ctrack.hash[n]; } + // for(var n in args.q) { dat[n]=args.q[n]; } + // if(dat.sector_code||dat.sector_group) { dat.from+=",sector"; } + // if(dat.country_code) { dat.from+=",country"; } + // if(dat.location_latitude && dat.location_longitude) { dat.from+=",location"; } + + fetch.ajax_dat_fix(dat, args); + if (args.output == "count") { + // just count please + let y = ctrack.args.selected_year; //Date.UTC(ctrack.args.selected_year, 1, 1) / (1000 * 60 * 60 * 24); + dat.select = "count_aid"; + (dat.between = [y, "day_start", "day_end"]), delete dat.limit; + delete dat.orderby; + delete dat.groupby; + } + var eightyeight = 88; + fetch.ajax(dat, function(data) { + if (args.output == "count") { + ctrack.chunk( + args.chunk || "list_activities_count", + data.rows[0]["count_aid"] + ); + views.stats.calc(); + } else { + if (args.compare) { + data.rows.sort(args.compare); + } + + var s = []; + ctrack.args.chunks["table_header_amount"] = undefined; + if (data.rows.length == 0 && args.zerodata) { + s.push(plate.replace(args.zerodata, {})); + ctrack.args.chunks["table_header_amount"] = ""; + } + ctrack.chunk("list_activities_count", data.rows.length); + var a = []; + for (var i = 0; i < data.rows.length; i++) { + var v = data.rows[i]; + var d = {}; + d.num = i + 1; + d.funder = v.funder || "N/A"; + d.aid = encodeURIComponent(v.aid || "N/A"); + d.title = v.title || v.aid || "N/A"; + + d.date_start = "N/A"; + d.date_end = "N/A"; + if (v.day_start !== null) { + d.date_start = fetch.get_nday(v.day_start); + } + if (v.day_end !== null) { + d.date_end = fetch.get_nday(v.day_end); + } + + d.reporting = + iati_codes.publisher_names[v.reporting_ref] || + v.reporting || + v.reporting_ref || + "N/A"; + d.commitment = commafy( + "" + Math.floor(ctrack.convert_num("commitment", v)) + ); + d.spend = commafy("" + Math.floor(ctrack.convert_num("spend", v))); + d.currency = ctrack.display_usd; + d.pct = 0; + if (v.commitment && v.commitment != 0) { + d.pct = Math.floor(100 * v.spend / v.commitment); + if (d.pct < 0) { + d.pct = 0; + } + if (d.pct > 100) { + d.pct = 100; + } + } + a.push(d); + s.push(plate.replace(args.plate || "{list_activities_data}", d)); + } + ctrack.chunk(args.chunk || "list_activities_datas", s.join("")); + ctrack.chunk("total", data.rows.length); + + var cc = []; + cc[0] = ["aid", "title", "reporting", "commitment", "spend", "currency"]; + a.forEach(function(v) { + cc[cc.length] = [ + v.aid, + v.title, + v.reporting, + v.commitment, + v.spend, + v.currency + ]; + }); + ctrack.chunk( + (args.chunk || "list_activities_datas") + "_csv", + "data:text/csv;charset=UTF-8," + encodeURIComponent(csvw.arrayToCSV(cc)) + ); + } + if (args.callback) { + args.callback(data); + } + ctrack.display(); + }); +}; diff --git a/ctrack/js/view_stats.js b/ctrack/js/view_stats.js index 655f6d05..d23783fe 100644 --- a/ctrack/js/view_stats.js +++ b/ctrack/js/view_stats.js @@ -1,42 +1,40 @@ // Copyright (c) 2014 International Aid Transparency Initiative (IATI) // Licensed under the MIT license whose full text can be found at http://opensource.org/licenses/MIT - var view_stats = exports; exports.name = "view_stats"; -var ctrack = require("./ctrack.js") -var plate = require("./plate.js") -var iati = require("./iati.js") -var fetch = require("./fetch.js") +var ctrack = require("./ctrack.js"); +var plate = require("./plate.js"); +var iati = require("./iati.js"); +var fetch = require("./fetch.js"); -var views = require("./views.js") +var views = require("./views.js"); // the chunk names this view will fill with new data view_stats.chunks = [ - "total_projects", - "missing_projects", - "active_projects", - "ended_projects", - "planned_projects", - "numof_publishers", - "total_budget", - "total_expenditure", - "percent_of_activities_with_location" + "total_projects", + "missing_projects", + "active_projects", + "ended_projects", + "planned_projects", + "numof_publishers", + "total_budget", + "total_expenditure", + "percent_of_activities_with_location" ]; -view_stats.calc = function () { - var tot = ctrack.chunk("total_projects") || 0; - var num = ctrack.chunk("total_activities_with_location") || 0; - if (num < 1 || tot < 1) { - ctrack.chunk("percent_of_activities_with_location", 0); - } - else { - var pct = Math.ceil(100 * num / tot); - ctrack.chunk("percent_of_activities_with_location", pct); - } +view_stats.calc = function() { + var tot = ctrack.chunk("total_projects") || 0; + var num = ctrack.chunk("total_activities_with_location") || 0; + if (num < 1 || tot < 1) { + ctrack.chunk("percent_of_activities_with_location", 0); + } else { + var pct = Math.ceil(100 * num / tot); + ctrack.chunk("percent_of_activities_with_location", pct); + } - /* + /* var pt=parseInt(ctrack.chunk("total_projects"))||0; var pa=parseInt(ctrack.chunk("active_projects"))||0; @@ -54,103 +52,125 @@ view_stats.calc = function () { } */ -// console.log(pm); -} - + // console.log(pm); +}; // // Perform ajax call to get numof data // -view_stats.ajax = function (args) { - args = args || {}; - let y = Date.UTC(ctrack.args.selected_year, 1, 1) / (1000 * 60 * 60 * 24); - - var dat = { - "select": "sum_budget_value", - "from": "act,budget", - "budget": "budget", - "between":[y,"budget_day_start","budget_day_end"], - - }; - - fetch.ajax_dat_fix(dat, args); - // console.log('==================dat==================',JSON.stringify(dat)) - fetch.ajax(dat, args.callback || function (data) { - // console.log("Fetching Budget"); - // console.log(dat); - // console.log(JSON.stringify(data)); - - if (data.rows[0]) { - ctrack.chunk("total_budget", changeToMillions(data.rows[0]["sum_budget_value"], ctrack.convert_usd)); - } - ctrack.display(); // every fetch.ajax must call display once - }); - - var dat = { - "select": "stats", - "from": "act", - "between":[y,"day_start","day_end"], - }; - fetch.ajax_dat_fix(dat, args); - fetch.ajax(dat, args.callback || function (data) { - if (data.rows[0]) { - ctrack.chunk("total_projects", data.rows[0]["distinct_aid"]); - ctrack.chunk("numof_publishers", data.rows[0]["distinct_reporting_ref"]); - //ctrack.chunk("total_budget", changeToMillions(data.rows[0]["budget_value)"], ctrack.convert_usd)); - ctrack.chunk("total_expenditure", changeToMillions(data.rows[0]["sum_spend"], ctrack.convert_usd)); - } - - view_stats.calc(); - - ctrack.display(); // every fetch.ajax must call display once - }); - - - var dat = { - "select": "stats", - "from": "act,location", - "limit": -1, - "location_longitude_not_null": 1, // must have a location - "location_latitude_not_null": 1, // must have a location - }; - fetch.ajax_dat_fix(dat, args); - if (dat.country_code) { - dat.country_percent = 100; - } - - fetch.ajax(dat, args.callback || function (data) { - - if (data.rows[0]) { - ctrack.chunk("total_activities_with_location", data.rows[0]["distinct_aid"]); - } - view_stats.calc(); - - ctrack.display(); // every fetch.ajax must call display once - }); - - views.planned.ajax({output: "count"}); - views.active.ajax({output: "count"}); - views.ended.ajax({output: "count"}); - views.missing.ajax({output: "count"}); - +view_stats.ajax = function(args) { + args = args || {}; + let y = ctrack.args.selected_year; //Date.UTC(ctrack.args.selected_year, 1, 1) / (1000 * 60 * 60 * 24); + + var dat = { + select: "sum_budget_value", + from: "act,budget", + budget: "budget", + between: [y, "budget_day_start", "budget_day_end"] + }; + + fetch.ajax_dat_fix(dat, args); + // console.log('==================dat==================',JSON.stringify(dat)) + fetch.ajax( + dat, + args.callback || + function(data) { + // console.log("Fetching Budget"); + // console.log(dat); + // console.log(JSON.stringify(data)); + + if (data.rows[0]) { + ctrack.chunk( + "total_budget", + changeToMillions( + data.rows[0]["sum_budget_value"], + ctrack.convert_usd + ) + ); + } + ctrack.display(); // every fetch.ajax must call display once + } + ); + + var dat = { + select: "stats", + from: "act", + between: [y, "day_start", "day_end"] + }; + fetch.ajax_dat_fix(dat, args); + fetch.ajax( + dat, + args.callback || + function(data) { + if (data.rows[0]) { + ctrack.chunk("total_projects", data.rows[0]["distinct_aid"]); + ctrack.chunk( + "numof_publishers", + data.rows[0]["distinct_reporting_ref"] + ); + //ctrack.chunk("total_budget", changeToMillions(data.rows[0]["budget_value)"], ctrack.convert_usd)); + ctrack.chunk( + "total_expenditure", + changeToMillions(data.rows[0]["sum_spend"], ctrack.convert_usd) + ); + } + + view_stats.calc(); + + ctrack.display(); // every fetch.ajax must call display once + } + ); + + var dat = { + select: "stats", + from: "act,location", + limit: -1, + location_longitude_not_null: 1, // must have a location + location_latitude_not_null: 1 // must have a location + }; + fetch.ajax_dat_fix(dat, args); + if (dat.country_code) { + dat.country_percent = 100; + } + + fetch.ajax( + dat, + args.callback || + function(data) { + if (data.rows[0]) { + ctrack.chunk( + "total_activities_with_location", + data.rows[0]["distinct_aid"] + ); + } + view_stats.calc(); + + ctrack.display(); // every fetch.ajax must call display once + } + ); + + views.planned.ajax({ output: "count" }); + views.active.ajax({ output: "count" }); + views.ended.ajax({ output: "count" }); + views.missing.ajax({ output: "count" }); }; -var changeToMillions = function (number, currencyVal) { - function numberWithCommas(x) { - return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); - } - var prettyNumber = "?"; - number = Math.round(number * currencyVal); - - var digits = new Number(number).toString().length; - - if (digits > 6) { - number = number / (1000000); - var roundedNumber = Math.round(number); - prettyNumber = numberWithCommas(roundedNumber) + ' M'; - } else { - prettyNumber = new Number(number).toString(); - } - - return prettyNumber; -} +var changeToMillions = function(number, currencyVal) { + function numberWithCommas(x) { + return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); + } + var prettyNumber = "?"; + number = Math.round(number * currencyVal); + + var digits = new Number(number).toString().length; + + if (digits > 6) { + number = number / 1000000; + var roundedNumber = Math.round(number); + prettyNumber = numberWithCommas(roundedNumber) + " M"; + } else { + prettyNumber = new Number(number).toString(); + } + + return prettyNumber; +}; diff --git a/dportal/js/undg.js b/dportal/js/undg.js index 528a55de..20c0c8a0 100644 --- a/dportal/js/undg.js +++ b/dportal/js/undg.js @@ -1,7 +1,7 @@ //TODO code quality -var fs = require('fs'); +var fs = require("fs"); var sqlite3 = require("sqlite3").verbose(); -var path = '../dstore/db/dstore.sqlite'; +var path = "../dstore/db/dstore.sqlite"; var sipac = new sqlite3.Database(path); var chunkopts = {}; @@ -9,252 +9,311 @@ var json_iati_codes = require("../../dstore/json/iati_codes.json"); var un_agencies_data = require("../../dstore/json/un_agencies_data.json") || {}; var geojson = require("../../dstore/json/countries.geo.json"); -sipac.serialize(function () { - var d = new Date(); - var year = parseInt(d.getFullYear()); - var month = parseInt(d.getMonth()); - var day = parseInt(d.getDate()); - var r = Date.UTC(year, month, day) / (1000 * 60 * 60 * 24); - - un_agencies_data['total_un_agencies'] = Object.keys(json_iati_codes.un_publisher_names).length; - un_agencies_data['un_agencies_in_iati'] = Object.keys(json_iati_codes.iati_un_publishers).length; - un_agencies_data['totalSectors'] = Object.keys(json_iati_codes.sector).length; - - //fetch Total Budget - let budget = {}; - let project = {}; - let expense = {}; - let activeProject = {}; - - for (let y = year; y >= (year - 5); y--) { - let start = Date.UTC(y, 1, 1) / (1000 * 60 * 60 * 24); - let end = Date.UTC(y, 12, 31) / (1000 * 60 * 60 * 24); - sipac.get("SELECT TOTAL(budget_value) FROM act JOIN budget USING (aid) WHERE budget =? AND ? BETWEEN budget_day_start AND budget_day_end", ['budget', start], function (err, row) { - budget[y] = row["TOTAL(budget_value)"]; - un_agencies_data['total_budget'] = budget; - }); - - //fetch Total activities and expenditure - var sql = "SELECT COUNT(DISTINCT aid) , TOTAL(spend) FROM act where reporting_ref NOTNULL AND ? BETWEEN day_start AND day_end"; - sipac.get(sql, [start], function (err, data) { - project[y] = data['COUNT(DISTINCT aid)']; - expense[y] = data['TOTAL(spend)']; - un_agencies_data['total_projects'] = project; - un_agencies_data['total_expenditure'] = expense; - }); - - //fetch Total active activities - sql = "SELECT COUNT(DISTINCT aid) AS count_aid FROM act WHERE ? BETWEEN day_start AND day_end AND day_end >= ? AND day_length IS NOT NULL"; - sipac.get(sql, [start, r], function (err, data) { - activeProject[y] = data['count_aid']; - un_agencies_data["active_projects"] = activeProject; - }); - } - - sipac.get("SELECT TOTAL(budget_value) FROM act JOIN budget USING (aid) WHERE budget =?", ['budget'], function (err, row) { - budget['all'] = row["TOTAL(budget_value)"]; - un_agencies_data['total_budget'] = budget; - }); - - var sql = "SELECT COUNT(DISTINCT aid) , TOTAL(spend) FROM act where reporting_ref NOT NULL"; - sipac.get(sql, function (err, data) { - project['all'] = data['COUNT(DISTINCT aid)']; - expense['all'] = data['TOTAL(spend)']; - un_agencies_data['total_projects'] = project; - un_agencies_data['total_expenditure'] = expense; +sipac.serialize(function() { + var d = new Date(); + var year = parseInt(d.getFullYear()); + var month = parseInt(d.getMonth()); + var day = parseInt(d.getDate()); + var r = Date.UTC(year, month, day) / (1000 * 60 * 60 * 24); + + un_agencies_data["total_un_agencies"] = Object.keys( + json_iati_codes.un_publisher_names + ).length; + un_agencies_data["un_agencies_in_iati"] = Object.keys( + json_iati_codes.iati_un_publishers + ).length; + un_agencies_data["totalSectors"] = Object.keys(json_iati_codes.sector).length; + + //fetch Total Budget + let budget = {}; + let project = {}; + let expense = {}; + let activeProject = {}; + + for (let y = year; y >= year - 5; y--) { + // let start = Date.UTC(y, 1, 1) / (1000 * 60 * 60 * 24); + // let end = Date.UTC(y, 12, 31) / (1000 * 60 * 60 * 24); + + sipac.get( + "SELECT TOTAL(budget_value) FROM act JOIN budget USING (aid) WHERE budget =? AND ? BETWEEN cast(strftime('%Y', datetime(budget_day_start * 60 * 60 * 24, 'unixepoch')) as integer) and cast(strftime('%Y', datetime(budget_day_end * 60 * 60 * 24, 'unixepoch')) as integer)", + ["budget", y], + function(err, row) { + budget[y] = row["TOTAL(budget_value)"]; + un_agencies_data["total_budget"] = budget; + } + ); + + //fetch Total activities and expenditure + var sql = + "SELECT COUNT(DISTINCT aid) , TOTAL(spend) FROM act where reporting_ref NOTNULL AND ? BETWEEN cast(strftime('%Y', datetime(day_start * 60 * 60 * 24, 'unixepoch')) as integer) and cast(strftime('%Y', datetime(day_end * 60 * 60 * 24, 'unixepoch')) as integer)"; + sipac.get(sql, [y], function(err, data) { + project[y] = data["COUNT(DISTINCT aid)"]; + expense[y] = data["TOTAL(spend)"]; + un_agencies_data["total_projects"] = project; + un_agencies_data["total_expenditure"] = expense; }); - sql = "SELECT COUNT(DISTINCT aid) AS count_aid FROM act WHERE day_start <= " + r + " AND ( day_end >= " + r + " OR day_end IS NULL ) AND day_length IS NOT NULL"; - sipac.get(sql, function (err, data) { - activeProject['all'] = data['count_aid']; - un_agencies_data["active_projects"] = activeProject; + //fetch Total active activities + sql = + "SELECT COUNT(DISTINCT aid) AS count_aid FROM act WHERE ? BETWEEN cast(strftime('%Y', datetime(day_start * 60 * 60 * 24, 'unixepoch')) as integer) and cast(strftime('%Y', datetime(day_end * 60 * 60 * 24, 'unixepoch')) as integer) AND day_end >= ? AND day_length IS NOT NULL"; + sipac.get(sql, [y, r], function(err, data) { + activeProject[y] = data["count_aid"]; + un_agencies_data["active_projects"] = activeProject; }); - - //fetch Total countries - sql = "Select Distinct country_code from country"; - var arr = {}; - arr['global-regional'] = {}; - sipac.all(sql, function (err, data) { - for (var code in data) { - if (json_iati_codes['country'].hasOwnProperty(data[code]['country_code'])) { - arr[data[code]['country_code']] = json_iati_codes['country'][data[code]['country_code']]; - } else if (json_iati_codes['region'].hasOwnProperty(data[code]['country_code'])) { - arr[data[code]['country_code']] = json_iati_codes['region'][data[code]['country_code']]; - } else { - arr['global-regional'][data[code]['country_code']] = data[code]['country_code']; - } - } - un_agencies_data['countries'] = arr; - }); - - //fetch projects trends - sql = "Select day_start,day_end from act"; - var currentProjectTrend = {}; - sipac.all(sql, function (err, data) { - for (var i in data) { - var start_year = getYearFromTimeStamp(parseInt(data[i]['day_start']) * (1000 * 60 * 60 * 24)); - var end_year = getYearFromTimeStamp(parseInt(data[i]['day_end']) * (1000 * 60 * 60 * 24)); - currentProjectTrend = getCurrentTrends(currentProjectTrend, [start_year, end_year]); - } - un_agencies_data['un_current_trends'] = currentProjectTrend; - }); - - //fetch projects sector_group - - sql = "Select Distinct sector_code from sector"; - var sectorGroupList = {}; - sipac.all(sql, function (err, data) { - for (var i in data) { - if (typeof json_iati_codes['sector'][data[i].sector_code] != 'undefined') { - sectorGroupList[data[i].sector_code] = json_iati_codes['sector'][data[i].sector_code]; - } - } - un_agencies_data['sectors'] = sectorGroupList; - - }); - + } + + sipac.get( + "SELECT TOTAL(budget_value) FROM act JOIN budget USING (aid) WHERE budget =?", + ["budget"], + function(err, row) { + budget["all"] = row["TOTAL(budget_value)"]; + un_agencies_data["total_budget"] = budget; + } + ); + + var sql = + "SELECT COUNT(DISTINCT aid) , TOTAL(spend) FROM act where reporting_ref NOT NULL"; + sipac.get(sql, function(err, data) { + project["all"] = data["COUNT(DISTINCT aid)"]; + expense["all"] = data["TOTAL(spend)"]; + un_agencies_data["total_projects"] = project; + un_agencies_data["total_expenditure"] = expense; + }); + + sql = + "SELECT COUNT(DISTINCT aid) AS count_aid FROM act WHERE day_start <= " + + r + + " AND ( day_end >= " + + r + + " OR day_end IS NULL ) AND day_length IS NOT NULL"; + sipac.get(sql, function(err, data) { + activeProject["all"] = data["count_aid"]; + un_agencies_data["active_projects"] = activeProject; + }); + + //fetch Total countries + sql = "Select Distinct country_code from country"; + var arr = {}; + arr["global-regional"] = {}; + sipac.all(sql, function(err, data) { + for (var code in data) { + if ( + json_iati_codes["country"].hasOwnProperty(data[code]["country_code"]) + ) { + arr[data[code]["country_code"]] = + json_iati_codes["country"][data[code]["country_code"]]; + } else if ( + json_iati_codes["region"].hasOwnProperty(data[code]["country_code"]) + ) { + arr[data[code]["country_code"]] = + json_iati_codes["region"][data[code]["country_code"]]; + } else { + arr["global-regional"][data[code]["country_code"]] = + data[code]["country_code"]; + } + } + un_agencies_data["countries"] = arr; + }); + + //fetch projects trends + sql = "Select day_start,day_end from act"; + var currentProjectTrend = {}; + sipac.all(sql, function(err, data) { + for (var i in data) { + var start_year = getYearFromTimeStamp( + parseInt(data[i]["day_start"]) * (1000 * 60 * 60 * 24) + ); + var end_year = getYearFromTimeStamp( + parseInt(data[i]["day_end"]) * (1000 * 60 * 60 * 24) + ); + currentProjectTrend = getCurrentTrends(currentProjectTrend, [ + start_year, + end_year + ]); + } + un_agencies_data["un_current_trends"] = currentProjectTrend; + }); + + //fetch projects sector_group + + sql = "Select Distinct sector_code from sector"; + var sectorGroupList = {}; + sipac.all(sql, function(err, data) { + for (var i in data) { + if ( + typeof json_iati_codes["sector"][data[i].sector_code] != "undefined" + ) { + sectorGroupList[data[i].sector_code] = + json_iati_codes["sector"][data[i].sector_code]; + } + } + un_agencies_data["sectors"] = sectorGroupList; + }); }); -var getYearFromTimeStamp = function (timeStamp) { - var d = new Date(timeStamp); - return d.getFullYear(); +var getYearFromTimeStamp = function(timeStamp) { + var d = new Date(timeStamp); + return d.getFullYear(); }; function getCurrentTrends(currentProjectTrend, yearly) { - var year = 0; - if (yearly != 0) { - var diff = yearly[1] - yearly[0]; - for (var i = 0; i <= diff; i++) { - year = parseInt(yearly[0]) + i; - if (year in currentProjectTrend) { - currentProjectTrend[year] = currentProjectTrend[year] + 1; - } else { - currentProjectTrend[year] = 1; - } - } + var year = 0; + if (yearly != 0) { + var diff = yearly[1] - yearly[0]; + for (var i = 0; i <= diff; i++) { + year = parseInt(yearly[0]) + i; + if (year in currentProjectTrend) { + currentProjectTrend[year] = currentProjectTrend[year] + 1; + } else { + currentProjectTrend[year] = 1; + } } - return currentProjectTrend; -}; + } + return currentProjectTrend; +} sipac.close(); setTimeout(function generate() { - fs.writeFileSync(__dirname + "/../../dstore/json/un_agencies_data.json", JSON.stringify(un_agencies_data, null, '\t')); - //update the publisher chunk - var pubs = []; - for (var id in un_agencies_data["sectors"]) { - var name = un_agencies_data["sectors"][id]; - var d = { - name: name - } - pubs.push(d); - } - for (var id in json_iati_codes["un_publisher_names"]) { - var name = json_iati_codes["un_publisher_names"][id]; - var d = { - name: name, - id: id - }; - pubs.push(d); + fs.writeFileSync( + __dirname + "/../../dstore/json/un_agencies_data.json", + JSON.stringify(un_agencies_data, null, "\t") + ); + //update the publisher chunk + var pubs = []; + for (var id in un_agencies_data["sectors"]) { + var name = un_agencies_data["sectors"][id]; + var d = { + name: name + }; + pubs.push(d); + } + for (var id in json_iati_codes["un_publisher_names"]) { + var name = json_iati_codes["un_publisher_names"][id]; + var d = { + name: name, + id: id + }; + pubs.push(d); + } + pubs.sort(function(a, b) { + var ta = a.name.toUpperCase(); + var tb = b.name.toUpperCase(); + return ta < tb ? -1 : ta > tb ? 1 : 0; + }); + chunkopts["publishers"] = pubs; + + // auto update the countries chunk + var ccs = []; + for (var id in un_agencies_data["countries"]) { + var name = un_agencies_data["countries"][id]; + + if (id === "global-regional") { + name = "Regional and global"; } - pubs.sort(function (a, b) { - var ta = a.name.toUpperCase(); - var tb = b.name.toUpperCase(); - return (ta < tb) ? -1 : (ta > tb) ? 1 : 0; - }); - chunkopts["publishers"] = pubs; - - // auto update the countries chunk - var ccs = []; - for (var id in un_agencies_data["countries"]) { - - var name = un_agencies_data["countries"][id]; - - if (id === 'global-regional') { - name = 'Regional and global'; - } - if (name) { - var d = { - name: name, - id: id - }; - ccs.push(d); - } + if (name) { + var d = { + name: name, + id: id + }; + ccs.push(d); } - ccs.sort(function (a, b) { - var ta = a.name.toUpperCase(); - var tb = b.name.toUpperCase(); - return (ta < tb) ? -1 : (ta > tb) ? 1 : 0; - }); - chunkopts["countries"] = ccs; - - var sec = []; - var secId = []; - for (var id in un_agencies_data["sectors"]) { - var cat = id.substring(0, 3); - - if (secId.indexOf(cat) == -1) { - var s = { - name: json_iati_codes["sector_category"][cat], - id: cat - }; - sec.push(s); - secId.push(cat); - } + } + ccs.sort(function(a, b) { + var ta = a.name.toUpperCase(); + var tb = b.name.toUpperCase(); + return ta < tb ? -1 : ta > tb ? 1 : 0; + }); + chunkopts["countries"] = ccs; + + var sec = []; + var secId = []; + for (var id in un_agencies_data["sectors"]) { + var cat = id.substring(0, 3); + + if (secId.indexOf(cat) == -1) { + var s = { + name: json_iati_codes["sector_category"][cat], + id: cat + }; + sec.push(s); + secId.push(cat); } - - sec.sort(function (a, b) { - var ta = a.name.toUpperCase(); - var tb = b.name.toUpperCase(); - - return (ta < tb) ? -1 : (ta > tb) ? 1 : 0; - }); - - chunkopts["sector"] = JSON.stringify(sec); - chunkopts["sector_un_operates"] = JSON.stringify(Object.keys(un_agencies_data["sectors"]).length); - chunkopts["publisher_names_json"] = JSON.stringify(json_iati_codes["un_publisher_names"]); - chunkopts["iati_un_publishers"] = JSON.stringify(json_iati_codes["iati_un_publishers"]); - chunkopts["country_names_json"] = JSON.stringify(un_agencies_data["countries"]); - chunkopts["crs_countries_json"] = JSON.stringify(un_agencies_data["countries"]); - chunkopts["total_projects"] = JSON.stringify(un_agencies_data["total_projects"]); - chunkopts["active_projects"] = JSON.stringify(un_agencies_data["active_projects"]); - chunkopts["total_budget"] = JSON.stringify(un_agencies_data["total_budget"]); - chunkopts["total_expenditure"] = JSON.stringify(un_agencies_data["total_expenditure"]); - chunkopts["total_un_agencies"] = JSON.stringify(un_agencies_data["total_un_agencies"]); - chunkopts["un_agencies_in_iati"] = JSON.stringify(un_agencies_data["un_agencies_in_iati"]); - chunkopts["total_sector"] = JSON.stringify(un_agencies_data["totalSectors"]); - - - var arr = Object.keys(un_agencies_data["un_current_trends"]).map(function (k) { - return k; - }); - var newYear = new Date(); - var currentYear = newYear.getFullYear(); - var currentYearStart = currentYear - 5; - currentYearStart = currentYearStart.toString(); - var currentYearEnd = currentYear + 2; - currentYearEnd = currentYearEnd.toString(); - var arr = arr.slice(arr.indexOf(currentYearStart), arr.indexOf(currentYearEnd)); - var un_trending = {}; - arr.forEach(function (year) { - un_trending[year] = un_agencies_data["un_current_trends"][year]; - }); - chunkopts["un_current_trends"] = JSON.stringify(un_trending); - - chunkopts["geojson"] = JSON.stringify(geojson); - - generateText(chunkopts); - -}, 5000); + } + + sec.sort(function(a, b) { + var ta = a.name.toUpperCase(); + var tb = b.name.toUpperCase(); + + return ta < tb ? -1 : ta > tb ? 1 : 0; + }); + + chunkopts["sector"] = JSON.stringify(sec); + chunkopts["sector_un_operates"] = JSON.stringify( + Object.keys(un_agencies_data["sectors"]).length + ); + chunkopts["publisher_names_json"] = JSON.stringify( + json_iati_codes["un_publisher_names"] + ); + chunkopts["iati_un_publishers"] = JSON.stringify( + json_iati_codes["iati_un_publishers"] + ); + chunkopts["country_names_json"] = JSON.stringify( + un_agencies_data["countries"] + ); + chunkopts["crs_countries_json"] = JSON.stringify( + un_agencies_data["countries"] + ); + chunkopts["total_projects"] = JSON.stringify( + un_agencies_data["total_projects"] + ); + chunkopts["active_projects"] = JSON.stringify( + un_agencies_data["active_projects"] + ); + chunkopts["total_budget"] = JSON.stringify(un_agencies_data["total_budget"]); + chunkopts["total_expenditure"] = JSON.stringify( + un_agencies_data["total_expenditure"] + ); + chunkopts["total_un_agencies"] = JSON.stringify( + un_agencies_data["total_un_agencies"] + ); + chunkopts["un_agencies_in_iati"] = JSON.stringify( + un_agencies_data["un_agencies_in_iati"] + ); + chunkopts["total_sector"] = JSON.stringify(un_agencies_data["totalSectors"]); + + var arr = Object.keys(un_agencies_data["un_current_trends"]).map(function(k) { + return k; + }); + var newYear = new Date(); + var currentYear = newYear.getFullYear(); + var currentYearStart = currentYear - 5; + currentYearStart = currentYearStart.toString(); + var currentYearEnd = currentYear + 2; + currentYearEnd = currentYearEnd.toString(); + var arr = arr.slice( + arr.indexOf(currentYearStart), + arr.indexOf(currentYearEnd) + ); + var un_trending = {}; + arr.forEach(function(year) { + un_trending[year] = un_agencies_data["un_current_trends"][year]; + }); + chunkopts["un_current_trends"] = JSON.stringify(un_trending); + + chunkopts["geojson"] = JSON.stringify(geojson); + + generateText(chunkopts); +}, 8000); function generateText(data) { - - let text = ""; - for (var key in data) { - var value = data[key] instanceof Object ? JSON.stringify(data[key]) : data[key]; - text += "#^" + key + "\n" + value + "\n\n"; - } - - fs.writeFileSync(__dirname + "/../source/\^.undg.txt", text); + let text = ""; + for (var key in data) { + var value = + data[key] instanceof Object ? JSON.stringify(data[key]) : data[key]; + text += "#^" + key + "\n" + value + "\n\n"; + } + + fs.writeFileSync(__dirname + "/../source/^.undg.txt", text); } diff --git a/dportal/source/index.^.html b/dportal/source/index.^.html index 77772a06..2521dd96 100644 --- a/dportal/source/index.^.html +++ b/dportal/source/index.^.html @@ -453,7 +453,7 @@

}); aa.push(""); - console.log("publishers",aa); + $("#publisher_dropmenu").html(aa.join("")); $("#publisher_dropmenu select").change(change); diff --git a/dstore/js/query.js b/dstore/js/query.js index fdb29229..47851670 100644 --- a/dstore/js/query.js +++ b/dstore/js/query.js @@ -1,41 +1,41 @@ // Copyright (c) 2014 International Aid Transparency Initiative (IATI) // Licensed under the MIT license whose full text can be found at http://opensource.org/licenses/MIT -var query=exports; +var query = exports; -var util=require('util'); -var fs=require('fs'); +var util = require("util"); +var fs = require("fs"); -var refry=require('./refry'); -var exs=require('./exs'); -var iati_xml=require('./iati_xml'); -var dstore_db=require("./dstore_db"); +var refry = require("./refry"); +var exs = require("./exs"); +var iati_xml = require("./iati_xml"); +var dstore_db = require("./dstore_db"); -var ls=function(a) { console.log(util.inspect(a,{depth:null})); } - - -query.mustbenumber=function(v) -{ - var n=Number(v); - if("number" == typeof n) - { - if(n==n) //check for nan - { - return n; - } - } - return undefined; -} - -query.maybenumber=function(v,ty) -{ - if(ty=="char") { return ""+v; } // force string - var n=query.mustbenumber(v); - if("number" == typeof n) { return n; } - return v; -} +var ls = function(a) { + console.log(util.inspect(a, { depth: null })); +}; +query.mustbenumber = function(v) { + var n = Number(v); + if ("number" == typeof n) { + if (n == n) { + //check for nan + return n; + } + } + return undefined; +}; +query.maybenumber = function(v, ty) { + if (ty == "char") { + return "" + v; + } // force string + var n = query.mustbenumber(v); + if ("number" == typeof n) { + return n; + } + return v; +}; // // 3 ways of passing query values @@ -48,778 +48,746 @@ query.maybenumber=function(v,ty) // //--REMOVED--- Finally you may perform a post request with json in the body. // -query.get_q = function(req){ - var q={}; - - q.start_time=Date.now(); - - var cp=function(f,unesc){ - for(var n in f) // single depth copy only - { - var v=f[n]; - if(unesc){ v=unesc(v); } // use unescape function? - if(q[n]===undefined) // only set if not exists, so call cp in order of priority from high to low - { - q[n]=v; - } - } - }; - -// use file extension as form - var aa=req.url.split("?"); - if(aa[0]) { - aa=aa[0].split("."); - if(aa[1]) { q.form=aa[1]; } - } - -// start with normal query - cp(req.query); - -// possibly containing an encoded json string? -// if(q._json) // expand json values for ?json=jsondata (also remove the this unexpanded value) -// { -// console.log(q._json); -// var t=JSON.parse(q._json); -// q.json=undefined; -// cp(t); -// } - -// finally the body may contain json so add that as well - if(req.body) - { - cp(req.body); - } - -// defaults - if(!q.from) - { - q.from="act"; // default act - } - if( q.form=="xml" || q.form=="html" ) // xml view so we... - { - if(q.from.indexOf("jml")==-1) // only add once - { - q.from+=",jml"; // ...need a jml join to spit out xml (jml is jsoned xml) - } - } - - -// we now have a json style chunk of data that consists of many possible inputs - return q; +query.get_q = function(req) { + var q = {}; + + q.start_time = Date.now(); + + var cp = function(f, unesc) { + for (var n in f) { + // single depth copy only + var v = f[n]; + if (unesc) { + v = unesc(v); + } // use unescape function? + if (q[n] === undefined) { + // only set if not exists, so call cp in order of priority from high to low + q[n] = v; + } + } + }; + + // use file extension as form + var aa = req.url.split("?"); + if (aa[0]) { + aa = aa[0].split("."); + if (aa[1]) { + q.form = aa[1]; + } + } + + // start with normal query + cp(req.query); + + // possibly containing an encoded json string? + // if(q._json) // expand json values for ?json=jsondata (also remove the this unexpanded value) + // { + // console.log(q._json); + // var t=JSON.parse(q._json); + // q.json=undefined; + // cp(t); + // } + + // finally the body may contain json so add that as well + if (req.body) { + cp(req.body); + } + + // defaults + if (!q.from) { + q.from = "act"; // default act + } + if (q.form == "xml" || q.form == "html") { + // xml view so we... + if (q.from.indexOf("jml") == -1) { + // only add once + q.from += ",jml"; // ...need a jml join to spit out xml (jml is jsoned xml) + } + } + + // we now have a json style chunk of data that consists of many possible inputs + return q; }; -query.getsql_select=function(q,qv){ - var ss=[]; - -// var stats_skip={ // ignore these columns -// "xml":true, -// "jml":true, -// "json":true -// }; - - - var ns=q[0]; - -// extra special calculations - var pcts={"country":true,"sector":true,"location":true}; - var percents=function(ret,name,agg){ - var mults=[]; - var aa=q.from.split(","); - for(var i=0;i", - "_lteq":"<=", - "_gteq":">=", - "_nteq":"!=", - "_eq":"=", - "_glob":"GLOB", - "_like":"LIKE", - "_null":"NULL", - "_not_null":"NOT NULL", - "":"=", - "_bt": "BETWEEN" - }; - - var niq=0; - for(var n in ns) - { - for( var qe in qemap ) - { - var ty=ns[n]; - var v=q[n+qe]; - var eq=qemap[qe]; - - if( v !== undefined ) // got a value - { - if( eq=="NOT NULL") { ss.push( " "+n+" IS NOT NULL " ); } - else - if( eq=="NULL") { ss.push( " "+n+" IS NULL " ); } - else - { - var t=typeof v; - if(t=="string") - { - var sa=v.split("|"); - var sb=/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.exec(sa[0]); - if( sa[0].length==10 && sb && sb.length==4 && ty=="int") // date string, convert to number if dest is an int - { - v=iati_xml.isodate_to_number(v); - - if(sa.length==2 && (/null/i).test(sa[1]) ) // allow an explicit or |null case - { - ss.push( " ( "+n+" "+eq+" "+dstore_db.text_plate(n+qe)+" OR "+n+" IS NULL ) " ); qv[dstore_db.text_name(n+qe)]=query.maybenumber(v,ty); - } - else - { - ss.push( " "+n+" "+eq+" "+dstore_db.text_plate(n+qe)+" " ); qv[dstore_db.text_name(n+qe)]=query.maybenumber(v,ty); - } - } - else - if(sa[1]) // there was an "|" - { - v=sa; - t="object"; // do object below - } - else - { - ss.push( " "+n+" "+eq+" "+dstore_db.text_plate(n+qe)+" " ); qv[dstore_db.text_name(n+qe)]=query.maybenumber(v,ty); - } - } - else - if(t=="number") - { - ss.push( " "+n+" "+eq+" "+dstore_db.text_plate(n+qe)+" " ); qv[dstore_db.text_name(n+qe)]=v; - } - - if(t=="object") // array, string above may also have been split into array - { - var so=[]; - for(var i=0;i0) { st.push( " OR " ); } - st.push( " "+n+" "+eq+v ); - } - st.push( " ) " ); - - ss.push(st.join("")); - } - } - } - } - } - } - - var v=q["text_search"]; - if( (ns["title"]) && (ns["description"]) && v ) // description and title and text_search available - { -//console.log("text_search "+v) - if(argv.pg) // can use better pg search code - { - ss.push( " to_tsvector('simple',title || ' ' || description) @@ plainto_tsquery('simple',"+dstore_db.text_plate("text_search")+") " ); - qv[dstore_db.text_name("text_search")]=v; - } - else // can only use old sqlite search code that only checks title - { - ss.push( " title LIKE "+dstore_db.text_plate("text_search") ); - qv[dstore_db.text_name("text_search")]="%"+v+"%"; - } - } - - - var ret=""; - if(ss[0]) { ret=" WHERE "+ss.join(" AND "); } - - return ret; +query.getsql_where = function(q, qv) { + var ss = []; + + var ns = q[0]; + + var joins = {}; + + var qemap = { + // possible comparisons + _lt: "<", + _gt: ">", + _lteq: "<=", + _gteq: ">=", + _nteq: "!=", + _eq: "=", + _glob: "GLOB", + _like: "LIKE", + _null: "NULL", + _not_null: "NOT NULL", + "": "=", + _bt: "BETWEEN" + }; + + var niq = 0; + for (var n in ns) { + for (var qe in qemap) { + var ty = ns[n]; + var v = q[n + qe]; + var eq = qemap[qe]; + + if (v !== undefined) { + // got a value + if (eq == "NOT NULL") { + ss.push(" " + n + " IS NOT NULL "); + } else if (eq == "NULL") { + ss.push(" " + n + " IS NULL "); + } else { + var t = typeof v; + if (t == "string") { + var sa = v.split("|"); + var sb = /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.exec(sa[0]); + if (sa[0].length == 10 && sb && sb.length == 4 && ty == "int") { + // date string, convert to number if dest is an int + v = iati_xml.isodate_to_number(v); + + if (sa.length == 2 && /null/i.test(sa[1])) { + // allow an explicit or |null case + ss.push( + " ( " + + n + + " " + + eq + + " " + + dstore_db.text_plate(n + qe) + + " OR " + + n + + " IS NULL ) " + ); + qv[dstore_db.text_name(n + qe)] = query.maybenumber(v, ty); + } else { + ss.push( + " " + n + " " + eq + " " + dstore_db.text_plate(n + qe) + " " + ); + qv[dstore_db.text_name(n + qe)] = query.maybenumber(v, ty); + } + } else if (sa[1]) { + // there was an "|" + v = sa; + t = "object"; // do object below + } else { + ss.push( + " " + n + " " + eq + " " + dstore_db.text_plate(n + qe) + " " + ); + qv[dstore_db.text_name(n + qe)] = query.maybenumber(v, ty); + } + } else if (t == "number") { + ss.push( + " " + n + " " + eq + " " + dstore_db.text_plate(n + qe) + " " + ); + qv[dstore_db.text_name(n + qe)] = v; + } + + if (t == "object") { + // array, string above may also have been split into array + var so = []; + for (var i = 0; i < v.length; i++) { + so.push(" " + dstore_db.text_plate(n + qe + "_" + i) + " "); + qv[dstore_db.text_name(n + qe + "_" + i)] = query.maybenumber( + v[i], + ty + ); + } + if (v.length == 2 && /null/i.test(v[1])) { + // allow an explicit or null case for base comparisons + ss.push( + " ( " + n + " " + eq + so[0] + " OR " + n + " IS NULL ) " + ); + qv[so[1].trim()] = undefined; // not going to be used + } else if (eq == "=") { + // make an IN statement + ss.push(" " + n + " IN (" + so.join(",") + ") "); + } else { + // explode into a bunch of OR statements + var st = []; + st.push(" ( "); + for (var i = 0; i < so.length; i++) { + var v = so[i]; + if (i > 0) { + st.push(" OR "); + } + st.push(" " + n + " " + eq + v); + } + st.push(" ) "); + + ss.push(st.join("")); + } + } + } + } + } + } + + var v = q["text_search"]; + if (ns["title"] && ns["description"] && v) { + // description and title and text_search available + //console.log("text_search "+v) + if (argv.pg) { + // can use better pg search code + ss.push( + " to_tsvector('simple',title || ' ' || description) @@ plainto_tsquery('simple'," + + dstore_db.text_plate("text_search") + + ") " + ); + qv[dstore_db.text_name("text_search")] = v; + } else { + // can only use old sqlite search code that only checks title + ss.push(" title LIKE " + dstore_db.text_plate("text_search")); + qv[dstore_db.text_name("text_search")] = "%" + v + "%"; + } + } + + var ret = ""; + if (ss[0]) { + ret = " WHERE " + ss.join(" AND "); + } + + return ret; }; -query.getsql_group_by=function(q,qv){ - var ss=[]; - - var ns=q[0]; - - if(q.groupby) - { - var qq; - qq=q.groupby.split(","); - for(var i=0;i0)&&(n<100)&&(n==n)) - { - ss.push(n+xtra); - } - } - } - } - - if(ss[0]) { return " ORDER BY "+ss.join(" , "); } - return ""; +query.getsql_order_by = function(q, qv) { + var ss = []; + + var ns = q[0]; + + if (q.orderby) { + var qq; + qq = q.orderby.split(","); + for (var i = 0; i < qq.length; i++) { + var xtra = ""; + var v = qq[i]; + if (v.slice(-1) == "-") { + xtra = " DESC"; + v = v.slice(0, -1); + } + if (ns[v]) { + // valid member names only + ss.push(v + xtra); + } else { + var n = parseInt(v); // or allow numerical indexes into results row + if (n > 0 && n < 100 && n == n) { + ss.push(n + xtra); + } + } + } + } + + if (ss[0]) { + return " ORDER BY " + ss.join(" , "); + } + return ""; }; -query.getsql_limit=function(q,qv){ - var ss=[]; - var limit=100; - - if( q.limit ) - { - var n=query.mustbenumber(q.limit); - if( "number" == typeof n) - { - limit=n - } - } - - if(limit>=0) - { - ss.push(" LIMIT "+limit+" "); - } - - if( q.page ) - { - var n=query.mustbenumber(q.page); - if( "number" == typeof n) - { - ss.push(" OFFSET "+n*limit+" "); - } - } - else - if( q.offset ) - { - var n=query.mustbenumber(q.offset); - if( "number" == typeof n) - { - ss.push(" OFFSET "+n+" "); - } - } - - if(ss[0]) { return ss.join(""); } - return ""; +query.getsql_limit = function(q, qv) { + var ss = []; + var limit = 100; + + if (q.limit) { + var n = query.mustbenumber(q.limit); + if ("number" == typeof n) { + limit = n; + } + } + + if (limit >= 0) { + ss.push(" LIMIT " + limit + " "); + } + + if (q.page) { + var n = query.mustbenumber(q.page); + if ("number" == typeof n) { + ss.push(" OFFSET " + n * limit + " "); + } + } else if (q.offset) { + var n = query.mustbenumber(q.offset); + if ("number" == typeof n) { + ss.push(" OFFSET " + n + " "); + } + } + + if (ss[0]) { + return ss.join(""); + } + return ""; }; -query.getsql_build_column_names=function(q,qv){ - - var ns={}; - for(var name in dstore_db.tables ) - { - for(var n in dstore_db.tables_active[name]) - { - ns[n]=dstore_db.tables_active[name][n]; - } - } +query.getsql_build_column_names = function(q, qv) { + var ns = {}; + for (var name in dstore_db.tables) { + for (var n in dstore_db.tables_active[name]) { + ns[n] = dstore_db.tables_active[name][n]; + } + } - q[0]=ns; // special array of valid column names + q[0] = ns; // special array of valid column names +}; +query.do_select_response = function(q, res, r) { + var send_json = function(r) { + if (q.callback) { + res.jsonp(r); // seems to only get headers right with a callback + } else { + res.set("charset", "utf8"); + res.set("Content-Type", "application/json"); + res.json(r); + } + }; + + res.set("charset", "utf8"); // This is always the correct answer. + + if (q.form == "html") { + res.set("Content-Type", "text/xml"); + + var xsl = + '\n'; + if (q.xsl == "!") { + xsl = ""; + } // disable pretty view + + res.write( + '\n' + + xsl + + '\n' + ); + + for (var i = 0; i < r.rows.length; i++) { + var v = r.rows[i]; + if (v && v.jml) { + res.write(refry.json(v.jml)); + res.write("\n"); + } + } + + res.end("\n"); + } else if (q.form == "xml") { + res.set("Content-Type", "text/xml"); + + res.write( + '\n' + ); + + for (var i = 0; i < r.rows.length; i++) { + var v = r.rows[i]; + if (v && v.jml) { + var d = JSON.parse(v.jml); + delete d["dstore:slug"]; // remove dstore tags + delete d["dstore:idx"]; + + res.write(refry.json(d)); + res.write("\n"); + } + } + + res.end("\n"); + } else if (q.form == "csv") { + res.set("Content-Type", "text/csv"); + + var head = []; + if (r.rows[0]) { + for (var n in r.rows[0]) { + head.push(n); + } + head.sort(); + res.write(head.join(",") + "\n"); + for (var i = 0; i < r.rows.length; i++) { + var v = r.rows[i]; + var t = []; + head.forEach(function(n) { + var s = "" + v[n]; + if ("string" == typeof s) { + // may need to escape + if (s.split(",")[1] || s.split("\n")[1]) { + // need to escape + s = '"' + s.split('"').join('""') + '"'; // wrap in quotes and double quotes in string + } + } + t.push(s); + }); + res.write(t.join(",") + "\n"); + } + res.end(""); + } else { + res.end(""); + } + } else if (q.form == "jcsv") { + // a jsoned csv (much smaller than json for large table data) + if (r.rows[0]) { + var head = []; + var ta = []; + for (var n in r.rows[0]) { + head.push(n); + } + head.sort(); // result order will be fixed + ta[0] = head; + for (var i = 0; i < r.rows.length; i++) { + var v = r.rows[i]; + var t = []; + ta[i + 1] = t; + head.forEach(function(n) { + t.push(v[n] || null); + }); + } + send_json(ta); + } else { + send_json([]); // nothing to see, but still trigger callback + } + } else { + r.time = (Date.now() - q.start_time) / 1000; + send_json(r); + } }; -query.do_select_response=function(q,res,r){ - - var send_json=function(r) - { - if(q.callback) - { - res.jsonp(r); // seems to only get headers right with a callback - } - else - { - res.set('charset','utf8'); - res.set('Content-Type', 'application/json'); - res.json(r); - } - }; - - res.set('charset','utf8'); // This is always the correct answer. - - if(q.form=="html") - { - res.set('Content-Type', 'text/xml'); - - var xsl='\n'; - if(q.xsl=="!") { xsl=""; } // disable pretty view - - res.write( '\n'+ - xsl+ - '\n'); - - for(var i=0;i\n'); - - } - else - if(q.form=="xml") - { - res.set('Content-Type', 'text/xml'); - - res.write( '\n'); - - for(var i=0;i\n'); - - } - else - if(q.form=="csv") - { - res.set('Content-Type', 'text/csv'); - - var head=[]; - if(r.rows[0]) - { - for(var n in r.rows[0]) { head.push(n); } - head.sort(); - res.write( head.join(",")+"\n" ); - for(var i=0;i