Needs work
Project:
Drupal core
Version:
main
Component:
documentation
Priority:
Normal
Category:
Bug report
Assigned:
Unassigned
Reporter:
Created:
16 Jan 2026 at 05:50 UTC
Updated:
28 Apr 2026 at 11:04 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #4
mondrakeIMHO we should not rely on the int value returned here. Only return TRUE or fail with an exception. The row count returned by different drivers is not consistent. See similar point for the UPSERT operation in #2547493-33: Add support for unique / primary key constraints composed of multiple fields for Upsert queries.
Comment #5
farzana.farook commentedI’ve updated the return type and opened an MR for this documentation fix.
Comment #6
smustgrave commentedBelieve your local may have been on 11.3 not 11.x, you may need to rebase your local branch and push that. MR is showing 1000s of changes
Comment #7
chi commentedRe: #4 Not knowing how many records have been updated will make the method useless in some cases.
Comment #8
mondrakeRetracted, see #11
#7 IMHO in a concurrent db that information returned here should be avoided as much as possible, given that rows affected (= the rows that the UPDATE conditions would return), and rows changed (= the affected rows actually changed) numbers may be impacted by concurrent operations.If knowing the precise number is absolutely necessary, then locking should be used, in pseudo:Comment #9
chi commentedI am thinking of DatabaseQueue which is currently use optimistic update.
Comment #10
mondrakeSorry I made a mistake in #8, will retract and rewrite it below.
Anyway:
affectedrows returns in Drupal the rows matching the condition, and not necessarily the changed ones. So I am not sure what #9 is actually doing.Comment #11
mondrake#7 IMHO in a concurrent db that information returned here should be avoided as much as possible, given that rows matched (= the rows that the UPDATE conditions would return), and rows changed (= the matched rows actually changed) numbers may be impacted by concurrent operations.
Also as per #3248575: Documentation conflict re: affected rows vs. matched rows, Drupal MySQL driver sets
which makes me suspect PgSQL and SQLite would have the same default behaviour, then.
If knowing the precise number is absolutely necessary, then locking should be used, in pseudo:
where {update conditions} should be set in a way to ensure matched rows=changed rows.
Comment #12
chi commentedplus
Together will always change these matching rows.
Comment #13
chi commentedAs I understood the
\Drupal\Core\Queue\DatabaseQueue::claimItemrelies on the UPDATE return value to figure out whether the item was successfully claimed.Comment #14
mondrakePostgres seems to return matched rows since 9.0 => https://www.php.net/manual/en/function.pg-affected-rows.php
Comment #15
mondrake#13 OK, but then a boolean is enough in this case, right? As long as it's not 0 we don't really need to know the exact number.
Comment #16
mondrakeSQLite viceversa seems to return the changed rows and not the matched ones => https://www.php.net/manual/en/sqlite3.changes.php
Comment #17
chi commentedCould you please direct me to the documentation for that? I couldn't find it in the PostgreSQL docs.
Comment #19
mondrakeMR!14392 is a proposal to return a
bool.Comment #20
mondrakeComment #21
chi commented@modrake, how would casting the return value to boolean make the result safer? If we cannot trust the number returned from UPDATE statement then we cannot trust its derivative (boolean).
Still wonder why you consider the return value unsafe. I suppose we just need to ensure behavior consistency across drivers ("matching" vs "changed"). And apparently "matching" is default behavior in all supported drivers.
The relevant Postgres documentation.
Comment #22
mondrakeI spot checked usage of
updateacross core's code base, and AFAICS the value returned by::executeis#21 yes casting to boolean is not safer per se, but in practice it does not look like the actual rowcount is used for its int value, apart in the update tests themselves.
I stand by #4. In fact IMHO for all of UPDATE, UPSERT and DELETE operations, what we should assume is that if the execution is not failing, then all the records identified by the conditions are eventually affected by the operation itself; trying to interpret the various row-affected or info internals seems to me not reliable (e.g. see the UPSERT related issue, or think someone in MySql set
Mysql::ATTR_FOUND_ROWStofalse: then if the row is found but not changed, update will return 0 or FALSE which is not what Drupal would expect, and in fact the row would be set to the values indicated by UPDATE).Comment #23
chi commentedI suppose contrib and custom projects may widely use it. So it would a BC break.
If casting is not safe why not just return nothing? Make the method void and advise using
SELECT FOR UPDATEstatement as workaround.Comment #24
mondrakeFully agree. That should be the end game. BC is in the way, of course.
Comment #26
mondrakeFiled #3568486: [meta] Change return of ::execute() DML/DDL methods (INSERT, UPDATE, UPSERT, DELETE, MERGE, TRUNCATE) to void not to derail this issue further.
Comment #27
mondrakeNW for #6
Comment #28
andypostComment #32
farzana.farook commented.
Comment #34
quietone commentedYes, this should be on main and so should the MR.
Comment #35
farzana.farook commentedComment #36
smustgrave commentedAppears to have a phpstan error. Most likely the baseline needs to be updated. Believe the artifact can be retrieved directly from the MR
Comment #37
farzana.farook commentedUpdated the phpstan baseline using the artifacts from the MR.
Comment #38
smustgrave commented@mondrake or @chi thoughts on what's in the MR?
Comment #39
chi commentedThere is another documentation bug that caused new ignores in PhpStan configuration.
\Drupal\Core\Database\ExceptionHandler::handleExecutionException should have return type
never, notvoid.Comment #41
mradcliffeI am removing the Novice tag from this issue because I am not sure what the next task is for a new contributor.
I’m using this documentation as a source: https://www.drupal.org/community/contributor-guide/task/triage-novice-is...
Comment #42
sivaji_ganesh_jojodae commentedUpdated the return type for
ExceptionHandler::handleExecutionException()as per #39.Removed outdated ignore rules from phpstan-baseline.php that are no longer triggered, fixing ignore.unmatched errors in the pipeline.
Comment #43
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.