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

optional JSON/JSONB passthrough for postgres #8141

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

softwareplumber
Copy link

Description of change

Fixes #8128 - though better than originally proposed. Implements mechanism for postgres JSON/JSONB types similar to HSTORE. Permits developers to use their own JSON parser which is essential for supporting high precision/scale in JSON, while maintaining backward compatibility.

Pull-Request Checklist

  • Code is up-to-date with the master branch
  • npm run lint passes with this change
  • npm run test passes with this change (though I've only run for postgres)
  • This pull request links relevant issues as Fixes #0000
  • There are new or updated unit tests validating the change
  • Documentation has been updated to reflect this change (only english)
  • The new commits follow conventions explained in CONTRIBUTING.md

@softwareplumber
Copy link
Author

softwareplumber commented Aug 30, 2021

The cockroachdb circleCI test failed with a segmentation fault... apparently after all the tests hard run. Did a local test with cockroachdb turned on and it seems to run OK.

@thansen8641
Copy link

This would be amazing!!!! 🤙🏻

@kordspace
Copy link

I really like how a large INT's can be represented in JSON but suddenly a JS parser won't be able to handle big INT's -- breaks JSON stringify... We need to use a different JSON parser and JSON stringify to deal with big INT's -- TypeORM can't use these big INTS, so if you want to be able to create an index on a 64 bit timestamp, in a JSON value. This fixes that!

export interface ColumnJsonOptions {

/**
* Return type of HSTORE column.
Copy link
Member

Choose a reason for hiding this comment

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

Wrong comment.

docs/entities.md Outdated Show resolved Hide resolved
@@ -128,6 +141,18 @@ export function Column(typeOrOptions?: ((type?: any) => Function)|ColumnType|(Co
if (options.type === "hstore" && !options.hstoreType)
options.hstoreType = reflectMetadataType === Object ? "object" : "string";

if (options.type === "json" && !options.jsonType)
Copy link
Member

Choose a reason for hiding this comment

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

I think better to remove this block for now to ensure its 100% non breaking change.

Copy link
Author

Choose a reason for hiding this comment

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

Spent quite a while thinking about this at the time. If a user manages map a string property of some entity to a json column in the database, in the expectation that json column will only ever contain strings, then of course their code will break if anyone ever inserts anything into that json column which is not a simple json string. The actual 'break' this change would imply is that in this corner case we would see quotes around their string when we didn't before (because the json parser is not being invoked). I felt that the balance was in favor of protecting the user from the consequence of their bad code design.

Copy link
Author

Choose a reason for hiding this comment

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

Happy to pull this out (and any associated unit test) if it is really the only way to get this merged, but since (for me) the only code that would break is arguably already broken, and this change should actually improve the behavior of that broken code, I think there's an argument for keeping this in. I'm going to fix everything else, rebase, and request a re-review.

@@ -56,6 +56,18 @@ export function PrimaryColumn(typeOrOptions?: ColumnType|PrimaryColumnOptions, o
if (!options.type)
throw new ColumnTypeUndefinedError(object, propertyName);

if (options.type === "json" && !options.jsonType)
Copy link
Member

Choose a reason for hiding this comment

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

same comment as above^

softwareplumber added a commit to SoftwarePlumbers/typeorm that referenced this pull request Nov 9, 2021
Per review of PR typeorm#8141, improve comments/docs where the original was unclear/misleading
@softwareplumber
Copy link
Author

There are other builds unrelated to this PR failing with QueryFailedError: SQLITE_ERROR: cannot start a transaction within a transaction, so I'm going to assume that is not related to my update.

@softwareplumber
Copy link
Author

Virtually certain the failing test due to e4d4636 @TheProgrammer21

@TheProgrammer21
Copy link
Contributor

Virtually certain the failing test due to e4d4636 @TheProgrammer21

@pleerock fixed the failing test on the master branch. I don't really get why it was failing initially since it ran without problems in my PR.

If the JSON retrieved from the database is simply to be re-serialized as a string, parsing
it into a javascript object is a waste of resources.
The default JSON parser does not support high numeric precision for JSON numbers, whereas
the JSONP format in postgres does. Using a value transformer with the new passthrough option
permits the use of a custom parser (e.g. json-bigint)

Closes typeorm#8128
Duplicate the core jsonp tests for a test entity which uses the jsonType: 'string' option
Per review of PR typeorm#8141, improve comments/docs where the original was unclear/misleading
Remove inadvertant duplication of log message, which may be causing
issues with some unit tests.
@softwareplumber
Copy link
Author

@TheProgrammer21 thanks that seems to have done the trick for me.

@pleerock
Copy link
Member

I don't think I want to merge this because it introduces double-way behavior.

I would like to understand why do we have a JSON.stringify there at all? @imnotjames maybe you know why?

@softwareplumber
Copy link
Author

softwareplumber commented Nov 18, 2021 via email

@pleerock
Copy link
Member

pleerock commented Nov 18, 2021

@softwareplumber and what node-pg gives you back? Does it gives an object?

I think appropriate solution to this problem is to find out why JSON.stringify was used and remove it if there are no strong reasons behind.

@softwareplumber
Copy link
Author

softwareplumber commented Nov 18, 2021 via email

@pleerock
Copy link
Member

@softwareplumber sorry for late answer here... But can't we came up with a more elegant solution? Something like:

what do you think about it?

@pleerock
Copy link
Member

I think this issue can be closed via #8766 . Let me know if not.

@pleerock pleerock closed this Mar 21, 2022
@softwareplumber
Copy link
Author

Yes, sure, this PR can be summed up as optionally pass through JSON. Whereas #8766 appears to be #always# pass through JSON, which was grits teeth my original proposal, excepting that this was shot down as a breaking change.

@pleerock
Copy link
Member

since its 0.3.x I permitted myself to introduce a breaking change to correctly support json/jsonb.

@pleerock
Copy link
Member

I had to revert my change introduced in #8766. More details in #8777. Also based on the problem I faced changes proposed in this PR won't play well. So, I'll ask to answer my question regarding to further implementation of this issue.

@pleerock pleerock reopened this Mar 22, 2022
@hinogi
Copy link

hinogi commented Aug 5, 2023

@softwareplumber it's been a long while, but can you maybe review the changes once more regarding big int replacement during stringify?

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.

PostgresDriver.preparePersistentValue for jsonb column should not call JSON.stringify if already a string
6 participants