silverstripe / silverstripe-sqlite3

SQLite3 DB Adapter for Silverstripe
BSD 3-Clause "New" or "Revised" License
8 stars 19 forks source link

Polymorphic database fields are bad news for reconstruction #45

Closed NightJar closed 5 years ago

NightJar commented 6 years ago

The new SS4 polymorphic relationship types cause issues when used in conjunction with sqlite. This manifests in the form of:

SilverStripe\Core\Injector\InjectorNotFoundException: ReflectionException: Class SilverStripeAssetsFile does not exist

As one may note, the backslashes are all missing from an otherwise valid (fully qualified) class name. This is odd, but I've not yet had time to track it down completely. I can say however that by the time it comes to generating the query, the desired slashes are already missing (i.e. in the row parameters), and is thus stored incorrectly.

My next step would be to look at the polymorphic database field types, and see how they prepare their data for storage. Something is different between MySQL and sqlite3, I've just not been able to track down quite where yet.

tractorcow commented 6 years ago

Sounds like a bug in enum fields with \ in values. Should be an easy fix.

NightJar commented 6 years ago

I assumed as such too. But I was unable to track down where that gets (un)set. Did I hear right in that you've been working on a fix? i.e. is it worth looking into this tonight? If you are working on a fix, could you please point me at a branch? I should like to test it tonight :)

tractorcow commented 6 years ago

No I haven't prioritised time to work on this I'm afraid.

dhensby commented 6 years ago

is this still a problem?

tractorcow commented 6 years ago

Yes it is.

NightJar commented 5 years ago

Something is going seriously wrong in fixture setup: Simplest incantation for reproduction: vendor/bin/phpunit --stop-on-error -v -d memory_limit=512M vendor/silverstripe/framework/tests/php/ORM/DataObjectTest.php '' flush=1

This is the second run through onBeforeWrite for this field, the first time seemed to generate sane configuration. However on writing after populate all relations we've got some bizarre values :|

image image

In these screenshots Favourite relationship is supposed to be SilverStripe\ORM\Tests\DataObjectTest\Team.team1, and there is no SecondFavourite set for this fixture. Instead they're both set to SilverStripeAssetsFile with the ID of 0.

NightJar commented 5 years ago

On first write either the link tracking or the asset access control extensions demolish the otherwise good record data - presumably by directly modifying the query as the results are not set into the DataObject::record as one would expect. The error is triggered on second write when the existing record is fresh-fetched from the database (I presume for comparison reasons), and then the bogus class name strikes.

NightJar commented 5 years ago

hahahaha, or not.

$ vendor/bin/phpunit --stop-on-error -v -d memory_limit=512M vendor/silverstripe/framework/tests/php/ORM/DataObjectTest.php '' flush=1 showqueries=1 | grep -A10 'FavouriteClass'
"FavouriteClass" TEXT DEFAULT 'SilverStripeAssetsFile',
"SecondFavouriteID" INTEGER(11) NOT NULL DEFAULT 0,
"SecondFavouriteClass" TEXT DEFAULT 'SilverStripeAssetsFile'
                )
0.0001s

Table setup writes a manky default in there :<

NightJar commented 5 years ago

OK. So.

This leaves us with an enum of 336 class names and default:"SilverStripe\Assets\File"

However because it's an enum, and enum is a non-portable MySQL specific thing, SQLite3SchemaManager does implement it's own handling method for that.

So anyways, PR #50