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
Public API for using custom data type parsers #6290
Comments
Your proposal sounds good to me - I would really like to get the API finalized and documented :) |
Great. One thing that needs to be taken into account though is #6270. For example, if a user overrides the parser/stringifier to use BigNumber for DECIMALs, the clone needs to be done with new BigNumber(value) and the comparison with value.equals(previousValue). I think in addition to parse() and stringify(), we need clone() and isEqual(). |
Probably a good idea, yea :) |
Also, stringify and parse should probably be instance methods because the may need to access parameters like binary for STRING etc. |
@janmeier what is the purpose of parserStore? I dont fully understand how the dialect specific data types override the base ones even though you use the base in your models... |
Whereas mysql wants the typeparser on connection level https://github.com/sequelize/sequelize/blob/master/lib/dialects/postgres/connection-manager.js#L41. To maintain the same behaviour across both (parsers are shared across all sequelize instances) I wanted to store the parsers outside of the connection mananger etc. for mysql. But using a map thats initialized outside of the class works fine as well :) https://github.com/sequelize/sequelize/blob/master/lib/dialects/mysql/connection-manager.js#L9
|
It turns out the implementation is really tricky. One thing that I would like to ensure is that users can save a reference to the default parser, because it can be quite complex. For example, if a user wants to override the ARRAY parser and stringifier to return a I feel like the whole inheritance of the dialect-specific data types is a pattern that imposes problems, and maybe we should move away from it. Maybe just provide the dialect-specific ones in a dialect object on the base data type? The object could be exported from the dialects types folder and required by the base data types, which is prettier than the exported closure. That way we don't have to recreate them in Would really like to hear some more opinions @sequelize |
To sum up the architectural problems here:
The solution would be to favor composition over inheritance, but I don't know exactly how. Maybe we can also leverage some JS features like |
Btw, node-postgres now supports connection-specific type parsers by using |
Definitely - Then we can get rid of the parser store thing, and you can have different parsers for different instances of sequelize |
https://github.com/sequelize/sequelize/blob/master/lib/sql-string.js#L39 This is a bit worrying, because |
Hmm yeah - That case handles dates inserted into raw queries ( |
any updates of this issues? I want to extend some datatypes properly. |
Currently trying to figure out how to deal with DECIMAL being strings in Sequelize v4, really need something like this. |
I'm using raw queries and I see |
Having specific data types returned as custom types is a common use case. For example, while it makes sense for sequelize to return DECIMALs as strings by default to keep the dependencies small, any application that handles any kind of complex monetary values that need to be manipulated will likely want to use something like bignumber.js to handle those.
Currently, there are two methods,
$stringify
(which is private?) andparse
. These partly sit on the base data types and then sometimes get overridden by the dialect data-types.There should be a way to define a custom parser and stringifier for a data type that
support for DataTypes.ARRAY(DataTypes.ENUM('value 1', 'value 2')) in postgres #1498 Proposal
Allow to set two methods on each data type,
parse
andstringify
.parse
at the moment is astatic
method, because it needs to be set in the libraries before a model is defined.stringify()
is an instance method and can therefor accessthis.options
. NOTE: It would be nice ifparse()
could be an instance method aswell for consistency. This may be changed before v4 is stable.The internal parse and stringify methods will be renamed to_parse
and_stringify
to make them explicitely private. These may be overridden by dialects. They always first check for the presence of aparse
and/orstringify
function on the data type that may have been provided by the user and use it to convert the value.The default implementation of
parse()
andstringify()
always delegate to the dialect-specific data-types with.call()
/.apply()
. The dialect that should be used when stringifying is given as adialect
option in theoptions
argument that some data types already accept. Data types are not replaced anymore at Model normalization with the dialect specific data types.A user can choose to fallback to the default behaviour by calling
super.stringify()
.Interface:
Questions about the current codebase
$stringify()
private, butparse()
not? No reasonparse()
static, but$stringify()
an instance method? Parsers need to be set at connection-level before Model creationstringify()
method? No reasonparse()
? E.g. why are there some data types that don't have this method defined, and how is this handled No reasonToDo
types
property - just use dialect objectsDataType.extend
(we have inheritance for that and will use delegation anyway)DataType.key
(we haveDataType.name
andDataType.prototype.toSql()
for that)The text was updated successfully, but these errors were encountered: