Skip to content

Commit

Permalink
fix: user earnings torrent count query
Browse files Browse the repository at this point in the history
Supposedly sql doesn't support referencing outer tables while inside a FROM clause. Mariadb seems to have an issue with this - but only on some databases. Not sure why.
  • Loading branch information
Roardom committed Feb 11, 2025
1 parent e45231b commit 21edfbd
Showing 1 changed file with 23 additions and 27 deletions.
50 changes: 23 additions & 27 deletions app/Http/Livewire/UserEarnings.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

use App\Models\BonEarning;
use App\Models\User;
use App\Models\Peer;
use App\Traits\LivewireSort;
use Illuminate\Support\Facades\DB;
use Livewire\Attributes\Computed;
Expand Down Expand Up @@ -63,12 +64,21 @@ final public function updatingSearch(): void
}

/**
* @return \Illuminate\Database\Eloquent\Collection<int|string, BonEarning>
* @return \Illuminate\Database\Eloquent\Collection<int, BonEarning>
*/
#[Computed]
final public function bonEarnings(): \Illuminate\Database\Eloquent\Collection
final public function bonEarnings(): \Illuminate\Support\Collection
{
$query = '';
$outerQuery = DB::query();
$innerQuery = Peer::query()
->join('history', fn ($join) => $join->on('history.torrent_id', '=', 'peers.torrent_id')->on('history.user_id', '=', 'peers.user_id'))
->join('torrents', 'peers.torrent_id', '=', 'torrents.id')
->where('peers.seeder', '=', true)
->where('peers.active', '=', true)
->where('peers.user_id', '=', $this->user->id)
->where('peers.created_at', '<', now()->subMinutes(30))
->where('torrents.name', 'LIKE', '%'.str_replace(' ', '%', $this->torrentName).'%')
->groupBy('peers.torrent_id');

foreach (BonEarning::with('conditions')->orderBy('position')->get() as $bonEarning) {
// Raw bindings are fine since all database values are either enums or numeric
Expand All @@ -90,34 +100,20 @@ final public function bonEarnings(): \Illuminate\Database\Eloquent\Collection
}.' '.$condition->operator.' '.$condition->operand2;
}

$query .= " WHEN bon_earnings.id = {$bonEarning->id} THEN MAX({$conditionQuery})";
$innerQuery->selectRaw("MAX({$conditionQuery}) AS bon_earning_{$bonEarning->id}");
$outerQuery->selectRaw("SUM(bon_earning_{$bonEarning->id}) AS bon_earning_{$bonEarning->id}");
}

$torrentCounts = $outerQuery->fromSub($innerQuery, 'peers_per_torrent')->first();

return BonEarning::query()
->addSelect([
'torrents_count' => DB::query()->fromSub(
DB::table('peers')
->select([
'peers.torrent_id',
DB::raw("CASE {$query} END AS torrent_count"),
])
->join('history', fn ($join) => $join->on('history.torrent_id', '=', 'peers.torrent_id')->on('history.user_id', '=', 'peers.user_id'))
->join('torrents', 'peers.torrent_id', '=', 'torrents.id')
->where('peers.seeder', '=', true)
->where('peers.active', '=', true)
->where('peers.user_id', '=', $this->user->id)
->where('peers.created_at', '<', now()->subMinutes(30))
->where('torrents.name', 'LIKE', '%'.str_replace(' ', '%', $this->torrentName).'%')
->groupBy(['peers.user_id', 'peers.torrent_id']),
'peers_per_torrent'
)
->select([
DB::raw('SUM(torrent_count)')
])
])
->orderBy('position')
->get()
->keyBy('id');
->map(function ($bonEarning) use ($torrentCounts) {
$bonEarning->setAttribute('torrents_count', $torrentCounts->{"bon_earning_{$bonEarning->id}"});

return $bonEarning;
});
}

/**
Expand Down Expand Up @@ -200,7 +196,7 @@ final public function query(): \Illuminate\Database\Query\Builder
}

/**
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator<\App\Models\Peer>
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator<Peer>
*/
#[Computed]
final public function torrents(): \Illuminate\Contracts\Pagination\LengthAwarePaginator
Expand Down

0 comments on commit 21edfbd

Please sign in to comment.