Skip to content

Commit

Permalink
feat(geo): add support for geography (#397)
Browse files Browse the repository at this point in the history
* first attempt to add geo. trying to locate which portions of code need to be touched. tests totally failing

* linted

* exclude geography from being promisified

* add geography to custom class list for encoding values

* add unit and system tests for geography

* Added test

* remove unnecessary comments

* update geography tests, removed skipped test

* add unit test for geography instance method

* add trailing commas
  • Loading branch information
steffnay authored Apr 2, 2019
1 parent 355d4d9 commit 8131b92
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 1 deletion.
56 changes: 55 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,10 @@ export class BigQuery extends common.Service {
value = BigQuery.timestamp(new Date(value * 1000));
break;
}
case 'GEOGRAPHY': {
value = BigQuery.geography(value);
break;
}
default:
break;
}
Expand Down Expand Up @@ -651,6 +655,38 @@ export class BigQuery extends common.Service {
return BigQuery.timestamp(value);
}

/**
* A geography value represents a surface area on the Earth
* in Well-known Text (WKT) format.
*
* @method BigQuery.geography
* @param {string} value The geospatial data.
*
* @example
* const {BigQuery} = require('@google-cloud/bigquery');
* const geography = BigQuery.geography('POINT(1, 2)');
*/

/**
* A geography value represents a surface area on the Earth
* in Well-known Text (WKT) format.
*
* @method BigQuery#geography
* @param {string} value The geospatial data.
*
* @example
* const {BigQuery} = require('@google-cloud/bigquery');
* const bigquery = new BigQuery();
* const geography = bigquery.geography('POINT(1, 2)');
*/
static geography(value: string) {
return new Geography(value);
}

geography(value: string) {
return BigQuery.geography(value);
}

/**
* Detect a value's type.
*
Expand Down Expand Up @@ -1504,7 +1540,15 @@ paginator.extend(BigQuery, ['getDatasets', 'getJobs']);
* that a callback is omitted.
*/
promisifyAll(BigQuery, {
exclude: ['dataset', 'date', 'datetime', 'job', 'time', 'timestamp'],
exclude: [
'dataset',
'date',
'datetime',
'geography',
'job',
'time',
'timestamp',
],
});

/**
Expand All @@ -1520,6 +1564,16 @@ export class BigQueryDate {
}
}

/**
* Geography class for BigQuery.
*/
export class Geography {
value: string;
constructor(value: string) {
this.value = value;
}
}

/**
* Timestamp class for BigQuery.
*/
Expand Down
1 change: 1 addition & 0 deletions src/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@ class Table extends common.ServiceObject {
'BigQueryDatetime',
'BigQueryTime',
'BigQueryTimestamp',
'Geography',
];
const constructorName = value.constructor.name;
const isCustomType =
Expand Down
35 changes: 35 additions & 0 deletions system-test/bigquery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ describe('BigQuery', () => {
const query = 'SELECT url FROM `publicdata.samples.github_nested` LIMIT 100';

const SCHEMA = [
{
name: 'place',
type: 'GEOGRAPHY',
},
{
name: 'id',
type: 'INTEGER',
Expand Down Expand Up @@ -1027,6 +1031,19 @@ describe('BigQuery', () => {
});
});

it('should work with GEOGRAPHY types', done => {
bigquery.query(
{
query: 'SELECT ? geography',
params: [bigquery.geography('POINT(1 2)')],
},
(err, rows) => {
assert.ifError(err);
assert.strictEqual(rows!.length, 1);
done();
});
});

it('should work with multiple types', done => {
bigquery.query(
{
Expand Down Expand Up @@ -1244,6 +1261,21 @@ describe('BigQuery', () => {
});
});

it('should work with GEOGRAPHY types', done => {
bigquery.query(
{
query: 'SELECT @place geography',
params: {
place: bigquery.geography('POINT(1 2)'),
},
},
(err, rows) => {
assert.ifError(err);
assert.strictEqual(rows!.length, 1);
done();
});
});

it('should work with multiple types', done => {
bigquery.query(
{
Expand Down Expand Up @@ -1299,6 +1331,7 @@ describe('BigQuery', () => {
const TIME = bigquery.time('14:00:00');
const TIMESTAMP = bigquery.timestamp(new Date());
const NUMERIC = new Big('123.456');
const GEOGRAPHY = bigquery.geography('POINT(1 2)');

before(() => {
table = dataset.table(generateName('table'));
Expand All @@ -1309,6 +1342,7 @@ describe('BigQuery', () => {
'time:TIME',
'timestamp:TIMESTAMP',
'numeric:NUMERIC',
'geography:GEOGRAPHY',
].join(', '),
});
});
Expand All @@ -1320,6 +1354,7 @@ describe('BigQuery', () => {
time: TIME,
timestamp: TIMESTAMP,
numeric: NUMERIC,
geography: GEOGRAPHY,
});
});
});
Expand Down
43 changes: 43 additions & 0 deletions test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const fakePfy = extend({}, pfy, {
'dataset',
'date',
'datetime',
'geography',
'job',
'time',
'timestamp',
Expand Down Expand Up @@ -243,6 +244,13 @@ describe('BigQuery', () => {
input,
};
});

sandbox.stub(BigQuery, 'geography').callsFake(input => {
return {
type: 'fakeGeography',
input,
};
});
});

it('should merge the schema and flatten the rows', () => {
Expand Down Expand Up @@ -299,6 +307,7 @@ describe('BigQuery', () => {
{v: 'date-input'},
{v: 'datetime-input'},
{v: 'time-input'},
{v: 'geography-input'},
],
},
expected: {
Expand Down Expand Up @@ -336,6 +345,10 @@ describe('BigQuery', () => {
input: 'time-input',
type: 'fakeTime',
},
geography: {
input: 'geography-input',
type: 'fakeGeography',
},
},
},
];
Expand Down Expand Up @@ -398,6 +411,11 @@ describe('BigQuery', () => {
type: 'TIME',
});

schemaObject.fields.push({
name: 'geography',
type: 'GEOGRAPHY',
});

const rawRows = rows.map(x => x.raw);
const mergedRows = BigQuery.mergeSchemaWithRows_(schemaObject, rawRows);

Expand Down Expand Up @@ -573,6 +591,31 @@ describe('BigQuery', () => {
});
});

describe('geography', () => {
const INPUT_STRING = 'POINT(1 2)';

it('should have the correct constructor name', () => {
const geography = BigQuery.geography(INPUT_STRING);
assert.strictEqual(geography.constructor.name, 'Geography');
});

it('should accept a string', () => {
const geography = BigQuery.geography(INPUT_STRING);
assert.strictEqual(geography.value, INPUT_STRING);
});

it('should call through to the static method', () => {
const fakeGeography = {value: 'foo'};

sandbox.stub(BigQuery, 'geography')
.withArgs(INPUT_STRING)
.returns(fakeGeography);

const geography = bq.geography(INPUT_STRING);
assert.strictEqual(geography, fakeGeography);
});
});

describe('getType_', () => {
it('should return correct types', () => {
assert.strictEqual(BigQuery.getType_(bq.date()).type, 'DATE');
Expand Down

0 comments on commit 8131b92

Please sign in to comment.