diff --git a/src/830into.js b/src/830into.js index 93428a74bc..1c0362ba3c 100755 --- a/src/830into.js +++ b/src/830into.js @@ -257,6 +257,10 @@ alasql.into.CSV = function (filename, opts, data, columns, cb) { columns .map(function (col) { var s = d[col.columnid]; + // Missing properties and null values both represent empty CSV fields. + if (s == null) { + s = ''; + } // escape the character wherever it appears in the field if (opt.quote !== '') { s = (s + '').replace(new RegExp('\\' + opt.quote, 'g'), opt.quote + opt.quote); diff --git a/test/test-csv-missing-properties.js b/test/test-csv-missing-properties.js new file mode 100644 index 0000000000..d2707c2c21 --- /dev/null +++ b/test/test-csv-missing-properties.js @@ -0,0 +1,27 @@ +if (typeof exports === 'object') { + var assert = require('assert'); + var alasql = require('..'); +} + +describe('Test 369 - CSV export with missing properties', function () { + it('A) Export missing properties as empty fields', function () { + var data = [ + {a: 1, b: 2, c: 3, d: 4}, + {a: 5, b: 6}, + ]; + var res = alasql('SELECT * INTO CSV({headers:true, utf8Bom:false}) FROM ?', [data]); + assert.deepStrictEqual(res, '"a";"b";"c";"d"\r\n1;2;3;4\r\n5;6;;\r\n'); + }); + + it('B) Preserve an explicit undefined string', function () { + var data = [{a: 'undefined'}]; + var res = alasql('SELECT * INTO CSV({headers:true, utf8Bom:false}) FROM ?', [data]); + assert.deepStrictEqual(res, '"a"\r\n"undefined"\r\n'); + }); + + it('C) Export null as empty but preserve an explicit null string', function () { + var data = [{a: null, b: 'null'}]; + var res = alasql('SELECT * INTO CSV({headers:true, utf8Bom:false}) FROM ?', [data]); + assert.deepStrictEqual(res, '"a";"b"\r\n;"null"\r\n'); + }); +});