Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: selectedFields on getRows not working correctly #712

Merged
merged 11 commits into from Jun 16, 2020
41 changes: 35 additions & 6 deletions src/bigquery.ts
Expand Up @@ -376,12 +376,33 @@ export class BigQuery extends common.Service {
*
* @param {object} schema
* @param {array} rows
* @param {array} selectedFields List of fields to return.
* If unspecified, all fields are returned.
* @returns {array} Fields using their matching names from the table's schema.
*/
static mergeSchemaWithRows_(
schema: TableSchema | TableField,
rows: TableRow[]
rows: TableRow[],
selectedFields?: string[]
) {
if (selectedFields && selectedFields!.length > 0) {
const selectedFieldsArray = selectedFields!.map(c => {
return c.split('.');
});

const currentFields = selectedFieldsArray.map(c => c.shift());
//filter schema fields based on selected fields.
schema.fields = schema.fields?.filter(
field =>
currentFields
.map(c => c!.toLowerCase())
.indexOf(field.name!.toLowerCase()) >= 0
);
selectedFields = selectedFieldsArray
.filter(c => c.length > 0)
.map(c => c.join('.'));
}

return arrify(rows)
.map(mergeSchema)
.map(flattenRows);
Expand All @@ -391,10 +412,10 @@ export class BigQuery extends common.Service {
let value = field.v;
if (schemaField.mode === 'REPEATED') {
value = (value as TableRowField[]).map(val => {
return convert(schemaField, val.v);
return convert(schemaField, val.v, selectedFields);
});
} else {
value = convert(schemaField, value);
value = convert(schemaField, value, selectedFields);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const fieldObject: any = {};
Expand All @@ -403,8 +424,12 @@ export class BigQuery extends common.Service {
});
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function convert(schemaField: TableField, value: any) {
function convert(
schemaField: TableField,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: any,
selectedFields?: string[]
) {
if (is.null(value)) {
return value;
}
Expand Down Expand Up @@ -434,7 +459,11 @@ export class BigQuery extends common.Service {
break;
}
case 'RECORD': {
value = BigQuery.mergeSchemaWithRows_(schemaField, value).pop();
value = BigQuery.mergeSchemaWithRows_(
schemaField,
value,
selectedFields
).pop();
break;
}
case 'DATE': {
Expand Down
6 changes: 5 additions & 1 deletion src/table.ts
Expand Up @@ -1678,7 +1678,11 @@ class Table extends common.ServiceObject {
callback!(err, null, null, resp);
return;
}
rows = BigQuery.mergeSchemaWithRows_(this.metadata.schema, rows || []);
rows = BigQuery.mergeSchemaWithRows_(
this.metadata.schema,
rows || [],
options.selectedFields ? options.selectedFields!.split(',') : []
);
callback!(null, rows, nextQuery, resp);
};

Expand Down
106 changes: 106 additions & 0 deletions test/table.ts
Expand Up @@ -2025,6 +2025,112 @@ describe('BigQuery/Table', () => {
done();
});
});

it('should return selected fields', done => {
const selectedFields = 'age';
const rows = [{f: [{v: 40}]}];
const schema = {
fields: [
{name: 'name', type: 'string'},
{name: 'age', type: 'INTEGER'},
],
};
const result = [{age: 40}];

table.metadata = {schema};

sandbox.restore();

table.request = (reqOpts: DecorateRequestOptions, callback: Function) => {
callback(null, {rows});
};

table.getRows({selectedFields}, (err: Error, rows: {}) => {
assert.ifError(err);
assert.deepStrictEqual(rows, result);
done();
});
});

it('should return selected fields from nested objects', done => {
const selectedFields = 'objects.nested_object.nested_property_1';
const rows = [
{
f: [
{
v: [
{
v: {
f: [
{
v: {
f: [
{
v: 'nested_property_1_value',
},
],
},
},
],
},
},
],
},
],
},
];
const schema = {
fields: [
{name: 'name', type: 'string'},
{
name: 'objects',
type: 'RECORD',
mode: 'REPEATED',
fields: [
{
name: 'nested_object',
type: 'RECORD',
fields: [
{
name: 'nested_property',
type: 'STRING',
},
{
name: 'nested_property_1',
type: 'STRING',
},
],
},
],
},
],
};
const result = [
{
objects: [
{
nested_object: {
nested_property_1: 'nested_property_1_value',
},
},
],
},
];

table.metadata = {schema};

sandbox.restore();

table.request = (reqOpts: DecorateRequestOptions, callback: Function) => {
callback(null, {rows});
};

table.getRows({selectedFields}, (err: Error, rows: {}) => {
assert.ifError(err);
assert.deepStrictEqual(rows, result);
done();
});
});
});

describe('insert', () => {
Expand Down