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(mariadb): do not automatically parse JSON fields by checking meta #15704

Merged
merged 4 commits into from Mar 27, 2023

Conversation

lesion
Copy link
Contributor

@lesion lesion commented Feb 23, 2023

This is related to an #14800

The type of field returned by mariadb does not depend on the version of mariadb, but on the version of mariadb WHEN the table was created!

https://mariadb.com/kb/en/result-set-packets/#field-types
For a JSON column, the column type field will be MYSQL_TYPE_STRING, but the extended type will indicate 'json'.

the connector use this field to decide to parse or not the response:
https://github.com/mariadb-corporation/mariadb-connector-nodejs/blob/59da962ce4ae6338bb14ed8854a70526b429911f/lib/cmd/decoder/text-decoder.js#L98

during a select the connector put fields details inside a "meta" key that could be used to check if returned value from the connector is already parsed or not:
https://github.com/mariadb-corporation/mariadb-connector-nodejs/blob/f25081715c9e1f24a10017e70787108d0d2ced01/documentation/promise-api.md#array-result-sets

a gist to test things:
https://gist.github.com/lesion/af0c7f1370ab6eb05cafdabd5b39ac33

@ephys
Copy link
Member

ephys commented Feb 23, 2023

Is there a way to add a regression test for this? I'm thinking create a text column using queryInterface.createTable but have the associated model use DataTypes.JSON?

query.js is likely to be completely rewritten in the future and a regression test would ensure we don't lose this logic

@lesion
Copy link
Contributor Author

lesion commented Feb 23, 2023

Is there a way to add a regression test for this? I'm thinking create a text column using queryInterface.createTable but have the associated model use DataTypes.JSON?
query.js is likely to be completely rewritten in the future and a regression test would ensure we don't lose this logic

I think we can test this by manually creating a table with a raw query using the two type of field mariadb uses for JSON and check if the results of a findAll are the same, could be something like:

  await sequelize.query("DROP TABLE IF EXISTS test");
  await sequelize.query(`CREATE TABLE test (id INTEGER AUTO_INCREMENT PRIMARY KEY,
    value1 longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
    value2 longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK(json_valid(value2)))`)
  await sequelize.query("INSERT INTO test (value1, value2) VALUES(?, ?)", { replacements: [JSON.stringify({ key: 'value' }), JSON.stringify({ key: 'value' })] } )
  const Test = sequelize.define('test', {
    value1: DataTypes.JSON,
    value2: DataTypes.JSON,
  }, {
    freezeTableName: true,
    timestamps: false
   })

  const ret = await Test.findAll({raw: true})

  console.error(typeof ret[0].value1, typeof ret[0].value2)
  console.error(ret[0].value1, ret[0].value2)

/** output without patch
string object
{"key":"value"} { key: 'value' }
**/

/** output with patch
object object
{ key: 'value' } { key: 'value' }
**/

lesion added a commit to lesion/sequelize that referenced this pull request Feb 24, 2023
@lesion
Copy link
Contributor Author

lesion commented Mar 20, 2023

Is there a way to add a regression test for this? I'm thinking create a text column using queryInterface.createTable but have the associated model use DataTypes.JSON?

query.js is likely to be completely rewritten in the future and a regression test would ensure we don't lose this logic

could we merge this? I wrote a unit test too https://github.com/sequelize/sequelize/pull/15704/files#diff-6a7c61f5188b4fa30990dd0dac3a0990087521e6a9d4431e10beecce7967573bR129-R153

Sorry to bother you, I'm worried because mariadb 10.8 is in debian stable so just and apt upgrade and this bug comes out

@WikiRik
Copy link
Member

WikiRik commented Mar 20, 2023

Can you resolve the conflicts with main? We'll take a look soon so we can merge

Copy link
Member

@WikiRik WikiRik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor suggestions to keep the test suite a little bit cleaner but the change and test itself looks good to me

packages/core/test/integration/json.test.js Outdated Show resolved Hide resolved
packages/core/test/integration/json.test.js Outdated Show resolved Hide resolved
WikiRik
WikiRik previously approved these changes Mar 20, 2023
@lesion
Copy link
Contributor Author

lesion commented Mar 20, 2023

nope, I need to take a look at the new test structure

Copy link
Member

@WikiRik WikiRik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good points from the linter

@WikiRik
Copy link
Member

WikiRik commented Mar 20, 2023

@ephys I'll give you a few days to look at it and then I'll merge

@WikiRik WikiRik requested a review from ephys March 20, 2023 18:47
@WikiRik WikiRik merged commit 0c0a4d4 into sequelize:main Mar 27, 2023
46 checks passed
@ephys
Copy link
Member

ephys commented Mar 27, 2023

I'm late but I'm fine with this change. I don't think it's the role of query.js to parse things but considering it's already here it's fine, and we'll redesign query.js in a future update

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants