Skip to content
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

Nonexistent values are not cached with field=myfield, causing unneeded SQL queries #1970

Open
tuomassalo opened this issue Sep 13, 2024 · 2 comments

Comments

@tuomassalo
Copy link

Short description of the issue

If I loop pages fetched with find("template=$template, field=mytext"), calling $page->mytext makes a database query for each page that do not have mytext value. This causes an "N+1 queries problem", potentially making a lot of unneeded queries.

Expected behavior

field=mytext should cache both the value and absence of a value, and no further database queries is needed when $page->mytext is accessed.

Actual behavior

For each page without mytext, $page->mytext triggers the query

SELECT field_mytext.data AS `mytext__data` FROM `field_mytext` WHERE field_mytext.pages_id=1015`

Optional: Suggestion for a possible fix

I suspect this to be a regression of processwire/processwire@4344df3.

I believe the code should read:

if(strpos($key, '__')) {
	if($value === null) {
		$row[$key] = 'null'; // ensure detected by later isset in foreach($joinFields)
	}
	$page->setFieldValue($key, $value, false); // <--- always do this, as before the regression
} else {
	$page->setForced($key, $value);
}

Steps to reproduce the issue

  1. Add a few pages
  2. Add a text field mytext to basic-page
  3. Fill mytext for one page
  4. Create and run this file:
<?php
$processwirePath = '/var/www/html/';
include($processwirePath . 'index.php');

$pages = $wire->pages->find("template=basic-page, field=mytext");

foreach($pages as $page) {
    echo $page->mytext;
}

$queries = $wire->database->getQueryLog();
echo '<p>Number queries: ' . count($queries) . '</p>';
foreach($queries as $query){
    echo '<p>' . htmlspecialchars($query) . '</p>';
}
  1. See that queries like the one above is executed for each page without mytext.

Setup/Environment

  • ProcessWire version: dev, vanilla installation with just one field added
  • (Optional) PHP version: 8.2
  • (Optional) MySQL version: MariaDB 10.5.26
@tuomassalo
Copy link
Author

@matjazpotocnik
Copy link
Collaborator

@tuomassalo, thanks for the update! So, can this issue be closed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants