Skip to content

Commit 4d9f37c

Browse files
Merge pull request #1068 from stephenplusplus/vlad--patch-1
bigquery: remove automatic `insertId` generation & allow specifying raw format
2 parents 44d27f4 + b9e5406 commit 4d9f37c

File tree

2 files changed

+110
-22
lines changed

2 files changed

+110
-22
lines changed

lib/bigquery/table.js

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
'use strict';
2222

2323
var arrify = require('arrify');
24-
var crypto = require('crypto');
2524
var duplexify = require('duplexify');
2625
var extend = require('extend');
2726
var format = require('string-format-obj');
@@ -849,6 +848,21 @@ Table.prototype.import = function(source, metadata, callback) {
849848
* @resource [Tabledata: insertAll API Documentation]{@link https://cloud.google.com/bigquery/docs/reference/v2/tabledata/insertAll}
850849
*
851850
* @param {object|object[]} rows - The rows to insert into the table.
851+
* @param {object=} options - Configuration object.
852+
* @param {boolean} options.ignoreUnknownValues - Accept rows that contain
853+
* values that do not match the schema. The unknown values are ignored.
854+
* Default: `false`.
855+
* @param {boolean} options.raw - If `true`, the `rows` argument is expected to
856+
* be formatted as according to the
857+
* [specification](https://cloud.google.com/bigquery/docs/reference/v2/tabledata/insertAll).
858+
* @param {boolean} options.skipInvalidRows - Insert all valid rows of a
859+
* request, even if invalid rows exist. Default: `false`.
860+
* @param {string} options.templateSuffix - Treat the destination table as a
861+
* base template, and insert the rows into an instance table named
862+
* "{destination}{templateSuffix}". BigQuery will manage creation of
863+
* the instance table, using the schema of the base template table. See
864+
* [Automatic table creation using template tables](https://cloud.google.com/bigquery/streaming-data-into-bigquery#template-tables)
865+
* for considerations when working with templates tables.
852866
* @param {function} callback - The callback function.
853867
* @param {?error} callback.err - An error returned while making this request.
854868
* @param {array} callback.insertErrors - A list of errors for insert failures.
@@ -879,6 +893,25 @@ Table.prototype.import = function(source, metadata, callback) {
879893
* table.insert(rows, insertHandler);
880894
*
881895
* //-
896+
* // Insert a row as according to the <a href="https://cloud.google.com/bigquery/docs/reference/v2/tabledata/insertAll">
897+
* // specification</a>.
898+
* //-
899+
* var row = {
900+
* insertId: '1',
901+
* json: {
902+
* INSTNM: 'Motion Picture Institute of Michigan',
903+
* CITY: 'Troy',
904+
* STABBR: 'MI'
905+
* }
906+
* };
907+
*
908+
* var options = {
909+
* raw: true
910+
* };
911+
*
912+
* table.insert(row, options, insertHandler);
913+
*
914+
* //-
882915
* // Handling the response.
883916
* //-
884917
* function insertHandler(err, insertErrors, apiResponse) {
@@ -897,23 +930,30 @@ Table.prototype.import = function(source, metadata, callback) {
897930
* // recommendations on handling errors.
898931
* }
899932
*/
900-
Table.prototype.insert = function(rows, callback) {
901-
var body = {
902-
rows: arrify(rows).map(function(row) {
903-
var rowObject = {};
904-
// Use the stringified contents of the row as a unique insert ID.
905-
var md5 = crypto.createHash('md5');
906-
md5.update(JSON.stringify(row));
907-
rowObject.insertId = md5.digest('hex');
908-
rowObject.json = row;
909-
return rowObject;
910-
})
911-
};
933+
Table.prototype.insert = function(rows, options, callback) {
934+
if (is.fn(options)) {
935+
callback = options;
936+
options = {};
937+
}
938+
939+
var json = extend(true, options, {
940+
rows: arrify(rows)
941+
});
942+
943+
if (!options.raw) {
944+
json.rows = arrify(rows).map(function(row) {
945+
return {
946+
json: row
947+
};
948+
});
949+
}
950+
951+
delete options.raw;
912952

913953
this.request({
914954
method: 'POST',
915955
uri: '/insertAll',
916-
json: body
956+
json: json
917957
}, function(err, resp) {
918958
if (err) {
919959
callback(err, null, resp);
@@ -928,7 +968,7 @@ Table.prototype.insert = function(rows, callback) {
928968
reason: error.reason
929969
};
930970
}),
931-
row: body.rows[insertError.index].json
971+
row: json.rows[insertError.index].json
932972
};
933973
});
934974

test/bigquery/table.js

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
var arrify = require('arrify');
2020
var assert = require('assert');
21-
var crypto = require('crypto');
2221
var extend = require('extend');
2322
var mockery = require('mockery');
2423
var nodeutil = require('util');
@@ -918,14 +917,19 @@ describe('BigQuery/Table', function() {
918917
{ state: 'MI', gender: 'M', year: '2015', name: 'Berkley', count: '0' }
919918
];
920919

920+
var rawData = [
921+
{ insertId: 1, json: data[0] },
922+
{ insertId: 2, json: data[1] },
923+
{ insertId: 3, json: data[2] },
924+
{ insertId: 4, json: data[3] },
925+
{ insertId: 5, json: data[4] },
926+
];
927+
921928
var dataApiFormat = {
922929
rows: data.map(function(row) {
923-
var rowObject = {};
924-
var md5 = crypto.createHash('md5');
925-
md5.update(JSON.stringify(row));
926-
rowObject.insertId = md5.digest('hex');
927-
rowObject.json = row;
928-
return rowObject;
930+
return {
931+
json: row
932+
};
929933
})
930934
};
931935

@@ -995,6 +999,50 @@ describe('BigQuery/Table', function() {
995999
done();
9961000
});
9971001
});
1002+
1003+
it('should insert raw data', function(done) {
1004+
table.request = function(reqOpts) {
1005+
assert.equal(reqOpts.method, 'POST');
1006+
assert.equal(reqOpts.uri, '/insertAll');
1007+
assert.deepEqual(reqOpts.json, { rows: rawData });
1008+
assert.strictEqual(reqOpts.json.raw, undefined);
1009+
done();
1010+
};
1011+
1012+
var opts = { raw: true };
1013+
table.insert(rawData, opts, done);
1014+
});
1015+
1016+
it('should accept options', function(done) {
1017+
var opts = {
1018+
ignoreUnknownValues: true,
1019+
skipInvalidRows: true,
1020+
templateSuffix: 'test'
1021+
};
1022+
1023+
table.request = function(reqOpts) {
1024+
assert.equal(reqOpts.method, 'POST');
1025+
assert.equal(reqOpts.uri, '/insertAll');
1026+
1027+
assert.strictEqual(
1028+
reqOpts.json.ignoreUnknownValues,
1029+
opts.ignoreUnknownValues
1030+
);
1031+
assert.strictEqual(
1032+
reqOpts.json.skipInvalidRows,
1033+
opts.skipInvalidRows
1034+
);
1035+
assert.strictEqual(
1036+
reqOpts.json.templateSuffix,
1037+
opts.templateSuffix
1038+
);
1039+
1040+
assert.deepEqual(reqOpts.json.rows, dataApiFormat.rows);
1041+
done();
1042+
};
1043+
1044+
table.insert(data, opts, done);
1045+
});
9981046
});
9991047

10001048
describe('query', function() {

0 commit comments

Comments
 (0)