googleapis / googleapis/google-cloud-node
Unable to use field name "type" of type INTEGER with params and UNNEST function.
- Dominant language
- TypeScript
- Stars
- 3.2k
- Forks
- 712
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 99
Description
### Please make sure you have searched for information in the following guides.
- [x] Search the issues already opened: https://github.com/GoogleCloudPlatform/google-cloud-node/issues
- [x] Search StackOverflow: http://stackoverflow.com/questions/tagged/google-cloud-platform+node.js
- [x] Check our Troubleshooting guide: https://github.com/googleapis/google-cloud-node/blob/main/docs/troubleshooting.md
- [x] Check our FAQ: https://github.com/googleapis/google-cloud-node/blob/main/docs/faq.md
- [x] Check our libraries HOW-TO: https://github.com/googleapis/gax-nodejs/blob/main/client-libraries.md
- [x] Check out our authentication guide: https://github.com/googleapis/google-auth-library-nodejs
- [x] Check out handwritten samples for many of our APIs: https://github.com/GoogleCloudPlatform/nodejs-docs-samples
### A screenshot that you have tested with "Try this API".
### Link to the code that reproduces this issue. A link to a **public** Github Repository or gist with a minimal reproduction.
https://gist.github.com/
### A step-by-step description of how to reproduce the issue, based on the linked reproduction.
1. Create a project, dataset, and table in bigquery with following Schema
```
[
{
"name": "id",
"type": "INTEGER",
"mode": "REQUIRED",
"description": ""
},
{
"name": "name",
"type": "STRING",
"mode": "NULLABLE",
"description": ""
},
{
"name": "type",
"type": "INTEGER",
"mode": "REQUIRED",
"description": ""
},
]
```
2. In a Node environment
3. Run `npm i @google-cloud/bigquery`
4. Replicate this bigquery SDK usage with proper credentials:
```
import { BigQuery } from '@google-cloud/bigquery';
const bigquery = new BigQuery({
projectId: "big-query-project",
credentials: credentials // TODO add valid credentials
});
bigquery.query({
query: `
MERGE \`project.dataset.table\` T
USING UNNEST(@rows) R
ON
T.id = R.id
WHEN MATCHED THEN
UPDATE set
name = R.name,
type = R.type,
WHEN NOT MATCHED THEN
INSERT (
id,
name,
type,
)
VALUES (
R.id
R.name,
R.type,
)
`,
params: {
rows: [
{ id: 1, name: 'name', type: 11 },
]
},
types: {
rows: [
{
id: 'INTEGER',
name: 'STRING',
type: 'INTEGER',
}
]
},
location: 'US'
});
```
### A clear and concise description of what the bug is, and what you expected to happen.
```
import { BigQuery } from '@google-cloud/bigquery';
const bigquery = new BigQuery({
projectId: "big-query-project",
credentials: credentials
});
bigquery.query({
query: `
MERGE \`project.dataset.table\` T
USING UNNEST(@rows) R
ON
T.id = R.id
WHEN MATCHED THEN
UPDATE set
name = R.name,
type = R.type,
WHEN NOT MATCHED THEN
INSERT (
id,
name,
type,
)
VALUES (
R.id
R.name,
R.type,
)
`,
params: {
rows: [
{ id: 1, name: 'name', type: 11 },
]
},
types: {
rows: [
{
id: 'INTEGER',
name: 'STRING',
type: 'INTEGER',
}
]
},
location: 'US'
});
```
There seems to be an issue when using a field named "type" of type "INTEGER" when querying with params and an UNNEST function.
When this is attempted it produces the following error:
> type.indexOf is not a function TypeError: type.indexOf is not a function
> at BigQuery._isCustomType (.../node_modules/@google-cloud/bigquery/build/src/bigquery.js:958:22)
> at BigQuery._getValue (.../node_modules/@google-cloud/bigquery/build/src/bigquery.js:954:25)
> at .../node_modules/@google-cloud/bigquery/build/src/bigquery.js:892:40
> at Array.map ()
> at BigQuery.valueToQueryParameter_ (.../node_modules/@google-cloud/bigquery/build/src/bigquery.js:891:63)
> at BigQuery.buildQueryParams_ (.../node_modules/@google-cloud/bigquery/build/src/bigquery.js:1068:51)
> at BigQuery.buildQueryRequest_ (.../node_modules/@google-cloud/bigquery/build/src/bigquery.js:1414:48)
> at BigQuery.query (.../node_modules/@google-cloud/bigquery/build/src/bigquery.js:1290:31)
> at .../node_modules/@google-cloud/promisify/build/src/index.js:57:28
> at new Promise ()
>
Looking in bigquery.js on line 946 there is the _getValue function:
```
static _getValue(value, type) {
if (value === null) {
return null;
}
if (value.type)
type = value;
return BigQuery._isCustomType(type) ? value.value : value;
}
```
In this function if the "value" has a property "type" then "type" is overwritten with "value".
In my scenario, the arguments to _getValue are` { id: 1, name: 'name', type: 11 } ` as "value" and `{type: 'STRUCT', structTypes: [{name: 'id', type: [Object]}, ...]}` as "type".
Because value.type evaluates to true, "type" is then overwritten with { id: 1, name: 'name', type: 11 }. Then when passed to _isCustomType (bigquery.js 954) that destructs "type" and attempts type.indexOf when type is 11 , thus causing the error.
```
static _isCustomType({ type }) {
return (type.indexOf('TIME') > -1 ||
type.indexOf('DATE') > -1 ||
type.indexOf('GEOGRAPHY') > -1 ||
type.indexOf('RANGE') > -1 ||
type.indexOf('BigQueryInt') > -1);
}
```
### A clear and concise description WHY you expect this behavior, i.e., was it a recent change, there is documentation that points to this behavior, etc. **
.
Contributor guide
Assessment
This issue has not been assessed yet.