diff --git a/composer.json b/composer.json
index 9185afbbd..e14f6301e 100644
--- a/composer.json
+++ b/composer.json
@@ -61,7 +61,7 @@
},
"extra": {
"branch-alias": {
- "4.x-dev": "4.4.x-dev"
+ "4.x-dev": "4.5.x-dev"
},
"expose": [
"client/images",
diff --git a/src/ORM/DataList.php b/src/ORM/DataList.php
index 28f538e9f..9110caabb 100644
--- a/src/ORM/DataList.php
+++ b/src/ORM/DataList.php
@@ -771,6 +771,20 @@ class DataList extends ViewableData implements SS_List, Filterable, Sortable, Li
return $this;
}
+ /**
+ * Returns a generator for this DataList
+ *
+ * @return \Generator&DataObject[]
+ */
+ public function getGenerator()
+ {
+ $query = $this->dataQuery->query()->execute();
+
+ while ($row = $query->record()) {
+ yield $this->createDataObject($row);
+ }
+ }
+
public function debug()
{
$val = "
" . static::class . "
";
diff --git a/src/ORM/FieldType/DBForeignKey.php b/src/ORM/FieldType/DBForeignKey.php
index 1c4532204..d8afaab8c 100644
--- a/src/ORM/FieldType/DBForeignKey.php
+++ b/src/ORM/FieldType/DBForeignKey.php
@@ -87,12 +87,29 @@ class DBForeignKey extends DBInt
// Add the count of the list to a cache for subsequent calls
if (!isset(static::$foreignListCache[$hasOneClass])) {
+ // Let the DB do the threshold check as it will be faster - depending on the SQL engine it might only have
+ // to count indexes
+ $dataQuery = $list->dataQuery()->getFinalisedQuery();
+
+ // Clear order-by as it's not relevant for counts
+ $dataQuery->setOrderBy(false);
+ // Remove distinct. Applying distinct shouldn't be required provided relations are not applied.
+ $dataQuery->setDistinct(false);
+
+ $dataQuery->setSelect(['over_threshold' => 'count(*) > ' . (int) $threshold]);
+ $result = $dataQuery->execute()->column('over_threshold');
+
+ // Checking for 't' supports PostgreSQL before silverstripe/postgresql@2.2
+ $overThreshold = !empty($result) && ($result[0] === 't' || (int) $result[0] === 1);
+
static::$foreignListCache[$hasOneClass] = [
- 'count' => $list->count(),
+ 'overThreshold' => $overThreshold,
];
}
- if (static::$foreignListCache[$hasOneClass]['count'] < $threshold) {
+ $overThreshold = static::$foreignListCache[$hasOneClass]['overThreshold'];
+
+ if (!$overThreshold) {
// Add the mapped list for the cache
if (!isset(static::$foreignListCache[$hasOneClass]['map'])) {
static::$foreignListCache[$hasOneClass]['map'] = $list->map('ID', $titleField);