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

spanner: Unable to insert multiple rows in a single table.insert/transaction.insert call when some rows lack a value for nullable columns #2411

Closed
jscinoz opened this issue Jun 27, 2017 · 7 comments
Assignees
Labels
api: spanner Issues related to the Spanner API. priority: p0 Highest priority. Critical issue. P0 implies highest priority. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.

Comments

@jscinoz
Copy link

jscinoz commented Jun 27, 2017

In transaction-request.js, there is the following (L687-695):

mutation[method] = {
  table: table,
  columns: Object.keys(keyVals[0]),
  values: keyVals.map(function(keyVal) {
    return Object.keys(keyVal).map(function(key) {
      return codec.encode(keyVal[key]);
    });
  })
};

There are at least two bugs here:

  1. When an array is provided to table.insert(), if some objects do not have a given key (which is perfectly valid if the column said key corresponds to is nullable), the array within values for this object will not be the same length as the columns array, and indices in columns will no longer correspond to the correct value in the values array for this row/object. This results in (best case) misleading error messages from Spanner about incorrect data types. Worse still, if it so happens that the value in the values array for this row and incorrect column index is the same type as the value for the correct column index, the insert request will succeed, and end up storing data in the wrong column entirely.

  2. If a consumer of this library works around the issue above by populating missing nullable keys with null, as the code above relies on the order of values returned by Object.keys, the newly added values will be at the end of the array returned by Object.keys (which returns keys in insertion order), and again, the indices between the columns array, and the values array for affected rows will no longer align, with the same end result as what occurs with issue 1 above.

This could be fixed by iterating over all rows (rather than naively assuming all rows have identical keys to the first row) and collecting all unique keys into a single array which is subsequently sorted lexically, to build the value for columns. Likewise, the value for values would be constructed by mapping over columns (rather than Object.keys(keyVal)) and pulling out the corresponding value from keyVal to pass to codec.encode.

@jscinoz jscinoz changed the title spanner: Incorrect handling of rows with missing nullable values in insert() spanner: Unable to insert multiple rows at once when some rows lack a value for nullable columns Jun 27, 2017
@jscinoz jscinoz changed the title spanner: Unable to insert multiple rows at once when some rows lack a value for nullable columns spanner: Unable to insert multiple rows in a single table.insert/transaction.insert call when some rows lack a value for nullable columns Jun 27, 2017
@stephenplusplus stephenplusplus added api: spanner Issues related to the Spanner API. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns. labels Jun 27, 2017
@stephenplusplus
Copy link
Contributor

Thanks for reporting, @jscinoz! Would you be willing to send a PR?

@jscinoz
Copy link
Author

jscinoz commented Jun 28, 2017

Sure thing, I will implement the fix as described above and send through a PR today.

jscinoz added a commit to AvokaTech/google-cloud-node that referenced this issue Jun 28, 2017
Prior to this change, attempting to insert multiple rows at once with Table#insert or
Transaction#insert where some rows lack a value for nullable columns would result in data attempting
to be inserted into the incorrect column, due to a flawed assumption in transaction-request.js that
every single row contains exact same set of columns, and that the order of keys returned by
Object.keys would be identical for each and every row.

This fixes googleapis#2411.
jscinoz added a commit to AvokaTech/google-cloud-node that referenced this issue Jun 28, 2017
Prior to this change, attempting to insert multiple rows at once with Table#insert or
Transaction#insert where some rows lack a value for nullable columns would result in data attempting
to be inserted into the incorrect column, due to a flawed assumption in transaction-request.js that
every single row contains exact same set of columns, and that the order of keys returned by
Object.keys would be identical for each and every row.

This fixes googleapis#2411.
@jscinoz
Copy link
Author

jscinoz commented Jun 28, 2017

PR created: #2417

@vkedia vkedia added the priority: p0 Highest priority. Critical issue. P0 implies highest priority. label Jun 30, 2017
@vkedia
Copy link
Contributor

vkedia commented Jun 30, 2017

@swcloud @bjwatson This would be a beta blocking issue since this can cause incorrect data to be stored in spanner.

@stephenplusplus stephenplusplus self-assigned this Jun 30, 2017
@stephenplusplus
Copy link
Contributor

I'm working on it now.

@vkedia
Copy link
Contributor

vkedia commented Jun 30, 2017

Thanks!

stephenplusplus pushed a commit to stephenplusplus/gcloud-node that referenced this issue Jun 30, 2017
Prior to this change, attempting to insert multiple rows at once with Table#insert or
Transaction#insert where some rows lack a value for nullable columns would result in data attempting
to be inserted into the incorrect column, due to a flawed assumption in transaction-request.js that
every single row contains exact same set of columns, and that the order of keys returned by
Object.keys would be identical for each and every row.

This fixes googleapis#2411.
@stephenplusplus
Copy link
Contributor

New PR in #2426.

stephenplusplus added a commit that referenced this issue Jul 5, 2017
…ns (#2426)

* spanner: Properly handle multi-row mutations with heterogeneous columns

Prior to this change, attempting to insert multiple rows at once with Table#insert or
Transaction#insert where some rows lack a value for nullable columns would result in data attempting
to be inserted into the incorrect column, due to a flawed assumption in transaction-request.js that
every single row contains exact same set of columns, and that the order of keys returned by
Object.keys would be identical for each and every row.

This fixes #2411.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: spanner Issues related to the Spanner API. priority: p0 Highest priority. Critical issue. P0 implies highest priority. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants