Add enum phpType support and enum migrations for PostgreSQL#128
Add enum phpType support and enum migrations for PostgreSQL#128oojacoboo wants to merge 8 commits intoperplorm:mainfrom
Conversation
…lasses. Add Postgresql support.
|
Interesting! Adjusting Not sure about the Postgres change though. Can you explain what it effectively adds? Does it more than add an alias column type, where you can write <column name="role_type" type="ENUM_NATIVE" sqlType="RoleType" />actaully more accurate than just <column name="role_type" sqlType="RoleType" />? Particularly when Perpl does not know anything about the type, except it's name? The advantage of using And I think we would need actual runtime tests for these changes (The perpl-test-docker image has Postgres |
|
So, I think you'll need to review how Postgres handles enums. That'll provide you with color here. You can also review how Doctrine defines enums, and how that works with Postgres.
<column name="role_type" type="ENUM_NATIVE" phpType="App\Model\RoleType" />This tells the generator that it's an enum (explicit intent) and that we need to use
Of course it can. But, I don't even know if the MySQL generator works for that? Where is the schema attribute to define all the enum named constants? How else is it going to generate the enum? Also, here is a bit from Doctrine on MySQL enum's shortcomings:
Yea, we can split off the Postgres type creation bit. That does need some work. We don't use Propel for migrations. I wonder if anyone actually does. -- As an aside here, I don't even think I'm not trying to complicate things here, but we're really trying to hang onto too much BC, for the sake of people that aren't even using enums presently. Couldn't the The custom attribute that's needed for the migrations would define what else is generated there. Doctrine does something like: columnDefinition="ENUM('visible', 'invisible')" |
|
Yes, please add Beyond that, I'm afraid I don't understand your answer. Why do you want to write <column name="role_type" type="ENUM_NATIVE" sqlType="RoleType" valueSet="Foo,Bar" />in Postgres? |
So, this is required for the migration generation to work for Postgres, since the If someone uses On adding the
|
63abbed to
329094b
Compare
…ration for CREATE TYPE and DROP TYPE, and add tests for enum behavior.
|
Okay, I've added support for This leaves 2 remaining items for enums before I'd consider it feature complete (not part of this PR):
|
|
Ok, let's recap:
? I think there is a misunderstanding here.
Ok, why should we restrict this? It is technically possible to use UnitEnum, just the same as BackedEnum. Yes, using BackedEnum is probably the better choice. But it might not be a decision the person writing the code can make. We should support both.
Assume yes. It is an important part of Propel/Perpl. And if this is not about migrations, I don't see what you get from declaring a column as
If people decide to make the jump from Propel2 to Perpl, I would prefer not to break their system when possible. Weighing necessity against possible negative impact, this does not seem to warrant breaking BC. It is not a front and center issue, and behavior can easily and comfortably be altered through config params:
It is, when you set the config parameter But feel free to provide a different evaluation than gain vs risk. BC is a slippery slope, I am happy to discuss clear parameters for when we should break BC and how to make these changes as painless as possible for users. Don't get me wrong, I do hope and look forward to a Perpl 3, where we make the changes to the interface permanent. I started a review, but I have to say, I am not comfortable doing these two unrelated things in the same PR. This is going to be confusing when ENUM means two different things in the same PR. Also, it is hard to say at the moment how big either of fixing |
Based on some of your comments, I assumed there were some misunderstandings for how Postgres handles enums, and it's important that we're speaking the same language here. That's all I meant here. If I misunderstood and you have a thorough understanding for how they work in Postgres, ignore this.
Correct, I went ahead and added support for migrations, not for myself, because I couldn't care less, but for the sake of feature completeness.
This comment is about something else entirely. Databases that store integers for enums, and are translated into string value constants through Propel are essentially To be clear - this is future discussion for generating enums in the Propel model and not implemented in this PR. Perpl does not generate PHP enums yet. But when it does, it should use
Right, which is why I went ahead and implemented the migration logic for enums. So, now MySQL and Postgres are properly supported for enum columns (not just MySQL).
Perpl needs to know that you're trying to "hydrate" an enum and not an object, when declaring
I completely agree. But enums were never supported. So, when we're adding
::thumbs_up::
See my comments above. We can continue this bit on #97 as well and focus on what's in this PR.
I can try to split them. But they're not unrelated. They're very tied together. For Postgres, you cannot define Now, to split them. I can add a hack as mentioned above about the |
|
From my understanding, you have to be careful not to mix up DB type with PHP type. You are mapping between them - they are not the same, and they are not as tightly coupled as (it sounds like) you say they are.
The same is true for enums imo. As you said yourself, PHP enum data can be stored in DB as A tight coupling between the two might be desirable for a developer, but it is easy to construct a scenario, where it is not:
Perpl has three ways to give "the" type of a field:
I think you argue that a
To me, it seems obvious that the default With all that, I hope it becomes clear why I think you are doing three things in this PR:
The first one I applaud, it fixes a bug in the system. Does that make sense, is it understandable? One way or another, creating the Postgres migration code affects different classes than making Phew, lots of text. Does that make sense? Are you d'accord? |
|
My main point regarding the types, was directed more towards how Doctrine handles this: https://www.doctrine-project.org/projects/doctrine-dbal/en/4.4/reference/types.html#mapping-matrix You can also override these. This isn't that dissimilar to Perpl's
What's wrong with using the
It generates the native PHP enum in the Perpl model. I thought I mentioned this in my last comment, but I think I removed it when I was making changes. This is still needed. Perpl needs to generate enums. The
You enroll yourself into a mental institution. But seriously, what's the point? Is this just for some BC reasons? If so, don't use enums at all. Set the
Absolutely not - wrong in fact. There is nothing "native" about using a string on the PHP side when the underlying database storage is using an enum.
Yes, this PR covers this.
There isn't any combination with
Absolutely, this should be expected!
Do not agree. You clearly use MySQL only and not Postgres. Your bias is shining through in your comments very strongly. I used to use MySQL, then switched to Postgres. I used MySQL for probably 20 years. I'd never switch back to MySQL, now, having switched to Postgres and knowing what I do. I'm not trying to make this into some kind of MySQL vs Postgres comparison. But, to say that, just because Postgres implements enums differently from MySQL, that there isn't a native implementation, is very wrong. In fact, Postgres' implementation for enums is far superior. For one, they can be shared across the schema. But you also don't have to drop and rebuild them to alter. MySQL's implementation is more like a value set constraint than anything. Regardless, the implementation for Postgres' enums is done in this PR.
100% disagree. In fact, to not do it is more confusing and incorrect. Can you please explain yourself more here - or maybe we can create another issue ticket to discuss this, since generating the enums isn't part of this PR. But the implementation is dead simple. There is nothing complex about it, as far as I can see. IT doesn't make the configuration of the schema less expressive either.
Unfortunately, they are very related. Take this bit:
I tried explaining this in my previous comment, but maybe I didn't do a good job. When you define So, without the schema
So, that all said, these two attributes (column |
|
What are you trying to archive with statements like
? It seems like you want to make me support your feature ideas (never formally outlined, discussed, or agreed on) by being argumentative in an unjustified tone. I don't see to what this is meant to succeed. |
Sorry if that seems too direct. However, that's exactly how I'm reading your comments around Postgres' support for enums. Maybe you can better explain where you're coming from here. I still do not understand your line of thinking, and have only been able to resolve it to a misunderstanding, or bias because of your own personal use of MySQL. At the moment, Perpl supports enum database types for MySQL only, as if MySQL is the only DB that actually has enums. Do you feel that's correct, that only MySQL supports enums "natively"? |
Summary
BackedEnumdetection forphpTypecolumns: hydration generatesEnumClass::from($value)instead ofnew EnumClass($value), and PDO binding extracts->valuefor scalar storageENUM_NATIVE) by passingtruetosetSetTypesMapping()inPgsqlPlatformand overridingbuildNativeEnumeratedColumnSqlType()to returnVARCHAR(PG enums are named types created viaCREATE TYPE, not inlineENUM()syntax — PDO handles them as strings)Changes
Backed enum
phpTypesupport (PropelTypes,Column,ObjectBuilder,ColumnCodeProducer):PropelTypes::isPhpBackedEnumType()/Column::isPhpBackedEnumType()— detects PHP backed enums viais_subclass_of(BackedEnum::class)ClassName::from($columnValue)instead ofnew ClassName($columnValue)$this->column?->valueextracts the scalar backing valueClassName::from($default)inapplyDefaultValues()andhasOnlyDefaultValues()PostgreSQL
ENUM_NATIVE(PgsqlPlatform):setSetTypesMapping(true)— enables native enum type supportbuildNativeEnumeratedColumnSqlType()returnsVARCHARsince PG enum columns are read/written as strings via PDOUsage
Where
RoleTypeis a PHP backed string enum:Generated code: