-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Support enumerated types #343
Comments
FYI in SQLite you could try to do something similar with a text column and CREATE TABLE track (
id INTEGER PRIMARY KEY,
track TEXT CHECK(track IN ('download', 'stream')) NOT NULL
); |
Is there currently a good way around this? Like a custom de/serializer? |
As an outsider who looked through the code to figure out if there is a way to do this, it appears that supporting a user-defined Postgres type requires knowing the object identifier that is in use for that type. In the case of enums, this requires extracting information from
select pt.typname, pt.typtype, pt.typcategory, pe.enumlabel, pt.oid
from pg_type pt
inner join pg_enum pe on pe.enumtypid = pt.oid
where pt.typcategory = 'E';
Since runtime database information is needed, some sort of codegen macro along the lines of |
I've put together a rough, partial implementation of Postgres enum support, which creates a macro called Unfortunately, there are currently a few assumptions about type definitions that make it difficult to use custom enum types in tables:
I haven't actually done the legwork necessary to know how to deal with encoding or decoding enum values to/from raw bytes for handoff with Postgres. I assume that this will essentially entail handling type-tagged integers. Finally, handling schemas correctly is on the back burner until everything else is taken care of. It'll require an additional join. |
I've been able to address (1) and (2), but getting everything working in the integration tests has run head-long into #348. If anyone has successfully figured out the minimal footprint of traits needed to make a simple, atomic SQL type, some documentation or example code would be welcome. |
Oh, wow! That sounds great! Thank you for digging into this!
Currently, the SQL types and the Rust types are divided; the table! macro
will contain a SQL type and a struct with e.g. Queryable has the ability to
deserialize these types into the actual Rust types it contains. What you
described sound like for an inferred enum, SQL and Rust type are the same.
I haven't thought much about this, maybe it makes sense. Just thought I'd
mention it.
@jethrogb was [on Gitter][1] a few weeks ago and wanted to implement a
custom type. Maybe you can get some additional information from the log
there.
Happy holidays!
[1]: https://gitter.im/diesel-rs/diesel?at=5849d6a8be9d43bc633778da
Stu Black <[email protected]> schrieb am Sa. 24. Dez. 2016 um 07:50:
… I've been able to address (1) and (2), but getting everything working in
the integration tests has run head-long into #348
<#348>. If anyone has
successfully figured out the minimal footprint of traits needed to make a
simple, atomic SQL type, some documentation or example code would be
welcome.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#343 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AABOX8AJ9cTIqXkGKoakndQpU0iVYeriks5rLMCugaJpZM4IlWGG>
.
|
My pleasure. I suspect that it will not be too difficult to extend this work to create Rust struct types automatically from user-created composite types in Postgres, and I'm also considering that.
That is exactly what the current implementation does. I have wondered a bit as to whether this is really the right thing to do, but I still believe it is. It might be a good idea store some metadata with the generated type (probably in a static impl of some There is probably a long-range design issue lurking behind the scenes here. I've already run into a few instances of code assuming that SQL types live in
I think I have the necessary traits implemented, but I'm still running into problems. A second pair of eyes will help once I have permission to share a patch. |
I just got the OK to contribute and copyright release from my friendly neighborhood corporate overlords, so I'll reinstate my fork soon. |
Feature bumps and deprecations from the 1.15 release and deprecation of I've pushed what was (more or less) working back in December to the custom_types_in_database_columns branch of my fork. I'd open a PR, but I don't think things are quite working yet. What's the deal with the test script? |
Try rebasing on master and running on beta |
The most significant test failures seem to be #571, which is not directly related to adding support for enums. With a fix patched in locally, the problem I am currently running into is that types which are declared in a dummy namespace by infer_enums!("dotenv:DATABASE_URL");
pub use self::__diesel_infer_enums::UserType; // Inserted by hand; shows that the type exists.
infer_schema!("dotenv:DATABASE_URL"); // Errors here because UserType isn't known. I have tried changing the table declarations generated by
I suspect that converting a literal "self" or "super" with A couple of different hacks (running I'll have to try to boil this down to a simple example to verify it, but this is acting an awful lot like the enum types whose declarations I'm generating are not visible in the code that generates the table schema. |
You can work around the question of how to look up dynamically generated types by requiring that the user specify the module where any non-builtin types can be found, so that's how things now work. This isn't great (and raises questions about how to deal with types derived from schemas, which one might reasonably want to live in sub-modules), but it looks like it works for now. I must have been recollecting wishfully when I said that I thought most tests were passing earlier. I'm now running into some deficiencies in implementing the interfaces needed to make a custom type queryable/insertable/updateable/etc. This is all in |
I will continue further discussion of the implementation I'm working on in #580. |
#580 has been closed as discussed there. (It needed to be factored apart and fell too far behind diesel main.) I have been swamped with events at work and in my personal life, and this has prevented me from pulling a set of new PRs together. I'd be happy to discuss this further with anyone who is interested in getting a PR together sooner, and I will share whatever I can put together, when I can. |
I just encountered this bug. Not having this feature means I'm (at least for now) switching from strongly-typed enums in my database to varchars... which is not great. I would love to have this feature. |
@dstu it would be nice if inferring schema is not required, other than perhaps creating a first example of a Rust enum (which might then be renamed, while keeping some annotation or so for the name used in Postgres... mapping)... and then connecting the dots upon actual connect, rather than having any kind of ids hardcoded. Or did I misunderstand you there when you mentioned "Since runtime database information is needed, some sort of codegen macro along the lines of infer_schema! seems necessary" ? |
FWIW, if working with pg enums in diesel meant having to define a rust annotated struct (or... enum?) to represent the pg enum, that'd seem totally reasonable to me. |
So I'm going to close this as a duplicate of #162. At this point, everything needed for absolute minimum "support" for PG enums is there. We even have a test case for this in Diesel itself. I'm aware that this requires more code than people would like right now (this is true of implementing new types in general, not just enums). #162 is the tracking issue for that, and is going to be the main focus of 1.1. Ideally you'll just need to provide an impl of At this point, I do not want to provide any special support for PG enums (e.g. TL;DR: Custom types in general are "supported". It's going to get more ergonomic in 1.1. We aren't going to provide special handling for PG enums. |
I don't necessarily agree with the decision, but I appreciate the way you're approaching the situation. I personally think enums are important enough to be a special case, but as long as it is possible to support them in Diesel, that's good enough for me. As you said, an outside crate could be developed to provide an opinionated solution to this issue that could act as a way to reduce boilerplate for those who are interested. Looking at the example code you linked to, it seems pretty reasonable to me. My only real question at this point: is using |
Not at the moment, but using `diesel print-schema` works
…On Sat, Dec 16, 2017, 3:11 PM Josh Leverette ***@***.***> wrote:
I don't necessarily agree with the decision, but I appreciate the way
you're approaching the situation. I personally think enums are important
enough to be a special case, but as long as it is *possible* to support
them in Diesel, that's good enough for me. As you said, an outside crate
could be developed to provide an opinionated solution to this issue that
could act as a way to reduce boilerplate for those who are interested.
Looking at the example code you linked to, it seems pretty reasonable to
me. My only real question at this point: is using infer_schema! is
possible with a database that has custom types in some/all of the tables?
I've been busy with other projects for awhile now, but from what I recall,
infer_schema! might have actually generated code which could not compile
in such cases, and I don't remember finding a way to inject the custom
types into the namespace that infer_schema! created.
—
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub
<#343 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABdWK3CVhaMcOvmOk96IWmiPhbmxc-mqks5tBD_6gaJpZM4IlWGG>
.
|
Just thought I'd mention to anyone who comes across this issue that I've made a crate to derive the necessary trait impls, it's up on crates.io. Feedback welcome. |
As @weiznich pointed out in gitter, it's inconvenient to provide custom types (including enums), so probably the best way to do is via the crates:
|
Diesel does not currently support enumerated types created with PostgreSQL.
Documentation on enumerated types can be found here.
More documentation on
CREATE TYPE
can be found here.Example
When compiling, the generated code expects a type named like the custom data type.
The text was updated successfully, but these errors were encountered: