-
Notifications
You must be signed in to change notification settings - Fork 11.3k
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
[5.6] Caching collections with database (PostgreSQL) cache driver doesn't work #25466
Comments
Did it every work for you? How did you define and create the cache table? Did you not get any error when storing it in PostgresSQL? Can you check the pgsql log? You probably think the database column has "enough space" (you mentioned this in spatie/laravel-permission#857 ) but I think you're running in a PgSQL specific problem: you cannot always expect store "null bytes" in PgSQL => see the SO answer => https://stackoverflow.com/a/28816294/47573 PHPs serialization format (but also JSON as I've experienced this a few times already) do support and make use of "null bytes" and always cause troubles with PgSQL if you want to use the |
@mfn No, it never worked for me before. The Schema::create('cache', function (Blueprint $table) {
$table->string('key')->unique();
$table->mediumText('value');
$table->integer('expiration');
}); I've read the SO answer that you linked... so it seems like the issue is that PostgreSQL can't store "null bytes" in I see that this is an issue that is related to PostgreSQL, because it can't store "null bytes". But can this be fixed on the PHP side, so that there is no need to store null bytes when caching a collection with the PostgreSQL driver? |
We could use Base64 encoding on PostgreSQL to fix this. We can either encode all values (breaking change) or only the ones that contain null bytes (non-breaking change). |
It does, it's the
My only gripe with this is that it increases the payload size and is a breaking change. Seems safer to me to simply figure out a proper datatype for to use with PgSQL? |
It's possible to implement Base64 encoding as a non-breaking change. I think this would be the better solution because it doesn't require any actions by the user. If we use a binary column, we have to add a note/warning to the documentation and adjust the |
You don't know if the cache table isn't read by some other (non-laravel) application too; not totally out of the world IMHO. |
To me any custom encoding feels like a hack. The serialization format has null bytes and the database supports it, you just have to use the correct type. IMHO educating is the proper "fix" here. |
But if only null bytes would be Base64 encoded, that shouldn't affect any other applications that read from the table because currently null bytes can't be stored at all. So I doubt that anybody is storing and reading those corrupted strings since you can't use them for anything. And all other, non-corrupted values would be unaffected by this change. If this is possible to do, it sounds like a better solution to me. About changing from |
It's not possible to convert the column with Using a binary column for PostgreSQL also requires changes to the So the |
@staudenmeir thanks for implementing this! <3 |
Hi @staudenmeir , would you mind to share where to implement the Base64 you suggested? |
@eternalBlast What Laravel version are you using? |
@staudenmeir I am using Laravel 5.5.45 LTS. |
This has only been fixed in Laravel 5.7. I'll submit a PR for 5.5. |
@eternalBlast It will be fixed in the next release. |
Okay @staudenmeir. Thanks a lot 👍 |
When will this fix available? @staudenmeir |
@eternalBlast not sure yet. I'll check in with Taylor but he's on vacation right now. |
Okay @driesvints. Please notify when it is done. Thanks. |
@eternalBlast Laravel 5.5.46 has been released. |
Thanks a lot. |
Description:
Caching collections when using the database driver doesn't work when using PostgreSQL. The issue seems to be that in PostgreSQL null bytes can't be stored in columns of the type
text
.This is what ends up being saved into the database:
This string was serialized but it's cut off and therefore corrupted, and it can not be unserialized. When trying to read it from cache, this exception is thrown:
This is an example SQL query that ends up saving a corrupted serialized string into the database:
Steps To Reproduce:
config/database.php
with the PostgreSQL driver and theconfig/cache.php
with the database drivercache
table withphp artisan cache:table
and migrate it$collection = User::limit(3)->get()
Cache::put('test', $collection, 5)
Cache::get('test')
In step 4, the corrupted string will be successfully saved into the database, without any exception or warning. In step 5, an exception will be thrown when trying to unserialize the corrupted string.
The text was updated successfully, but these errors were encountered: