Rewrite MultiTableSelect queries with ON

Instead of `USING(EbookId)`, it would be easier to handle
`MultiTableSelect` queries in `FromMultiTableRow()` if the queries used

`ON Projects.EbookId = Ebooks.Ebooks`

This is because `USING` will return only one `EbookId` column, but `ON`
will return all columns from both tables.
This commit is contained in:
Mike Colagrosso 2024-12-31 21:24:58 -07:00 committed by Alex Cabal
parent dad5df0059
commit 0e7bff5d82
3 changed files with 13 additions and 12 deletions

View file

@ -109,7 +109,7 @@ class DbConnection{
/** /**
* Execute a select query that returns a join against multiple tables. * Execute a select query that returns a join against multiple tables.
* *
* For example, `select * from Users inner join Posts using (UserId)`. * For example, `select * from Users inner join Posts on Users.UserId = Posts.UserId`.
* *
* The result is an array of rows. Each row is an array of objects, with each object containing its columns and values. For example, * The result is an array of rows. Each row is an array of objects, with each object containing its columns and values. For example,
* *
@ -122,6 +122,7 @@ class DbConnection{
* }, * },
* 'Posts' => { * 'Posts' => {
* 'PostId' => 222, * 'PostId' => 222,
* 'UserId' => 111,
* 'Title' => 'Lorem Ipsum' * 'Title' => 'Lorem Ipsum'
* } * }
* ], * ],
@ -132,13 +133,14 @@ class DbConnection{
* }, * },
* 'Posts' => { * 'Posts' => {
* 'PostId' => 444, * 'PostId' => 444,
* 'UserId' => 333,
* 'Title' => 'Dolor sit' * 'Title' => 'Dolor sit'
* } * }
* ] * ]
* ] * ]
* ``` * ```
* *
* **Important note:** When joining against two tables, SQL only returns one column for the join key (typically an ID value). Therefore, if both objects require an ID, the filler method must explicitly assign the ID to one of the two objects that's missing it. The above example shows this behavior: note how we join on `UserId`, but only the `Users` result has the `UserId` column, even though the `Posts` table also has a `UserId` column. * **Important note:** If the two tables above were joined via `using (UserId)` instead of `on Users.UserId = Posts.UserId`, the SQL query would return only one column for the join key (`UserId` in this case). Therefore, if both objects require an ID, the filler method must explicitly assign the ID to one of the two objects that's missing it. In the above example, the `Users` result would have the `UserId` column, and `Posts` would not.
* *
* @template T * @template T
* *

View file

@ -164,8 +164,8 @@ final class Ebook{
SELECT * SELECT *
from Projects from Projects
inner join Ebooks inner join Ebooks
using(EbookId) on Projects.EbookId = Ebooks.EbookId
where EbookId = ? where Ebooks.EbookId = ?
order by Projects.Created desc order by Projects.Created desc
', [$this->EbookId], Project::class); ', [$this->EbookId], Project::class);
} }
@ -183,8 +183,8 @@ final class Ebook{
SELECT * SELECT *
from Projects from Projects
inner join Ebooks inner join Ebooks
using(EbookId) on Projects.EbookId = Ebooks.EbookId
where EbookId = ? where Ebooks.EbookId = ?
and Status in (?, ?) and Status in (?, ?)
', [$this->EbookId, Enums\ProjectStatusType::InProgress, Enums\ProjectStatusType::Stalled], Project::class)[0] ?? null; ', [$this->EbookId, Enums\ProjectStatusType::InProgress, Enums\ProjectStatusType::Stalled], Project::class)[0] ?? null;
} }
@ -206,8 +206,8 @@ final class Ebook{
SELECT * SELECT *
from Projects from Projects
inner join Ebooks inner join Ebooks
using(EbookId) on Projects.EbookId = Ebooks.EbookId
where EbookId = ? where Ebooks.EbookId = ?
and Status in (?, ?) and Status in (?, ?)
', [$this->EbookId, Enums\ProjectStatusType::Completed, Enums\ProjectStatusType::Abandoned], Project::class); ', [$this->EbookId, Enums\ProjectStatusType::Completed, Enums\ProjectStatusType::Abandoned], Project::class);
} }

View file

@ -660,21 +660,21 @@ final class Project{
* @return array<Project> * @return array<Project>
*/ */
public static function GetAllByStatus(Enums\ProjectStatusType $status): array{ public static function GetAllByStatus(Enums\ProjectStatusType $status): array{
return Db::MultiTableSelect('SELECT * from Projects inner join Ebooks using (EbookId) where Projects.Status = ? order by regexp_replace(Title, \'^(A|An|The)\\\s\', \'\') asc', [$status], Project::class); return Db::MultiTableSelect('SELECT * from Projects inner join Ebooks on Projects.EbookId = Ebooks.EbookId where Projects.Status = ? order by regexp_replace(Title, \'^(A|An|The)\\\s\', \'\') asc', [$status], Project::class);
} }
/** /**
* @return array<Project> * @return array<Project>
*/ */
public static function GetAllByManagerUserId(int $userId): array{ public static function GetAllByManagerUserId(int $userId): array{
return Db::MultiTableSelect('SELECT * from Projects inner join Ebooks using (EbookId) where ManagerUserId = ? and Status in (?, ?) order by regexp_replace(Title, \'^(A|An|The)\\\s\', \'\') asc', [$userId, Enums\ProjectStatusType::InProgress, Enums\ProjectStatusType::Stalled], Project::class); return Db::MultiTableSelect('SELECT * from Projects inner join Ebooks on Projects.EbookId = Ebooks.EbookId where ManagerUserId = ? and Status in (?, ?) order by regexp_replace(Title, \'^(A|An|The)\\\s\', \'\') asc', [$userId, Enums\ProjectStatusType::InProgress, Enums\ProjectStatusType::Stalled], Project::class);
} }
/** /**
* @return array<Project> * @return array<Project>
*/ */
public static function GetAllByReviewerUserId(int $userId): array{ public static function GetAllByReviewerUserId(int $userId): array{
return Db::MultiTableSelect('SELECT * from Projects inner join Ebooks using (EbookId) where ReviewerUserId = ? and Status in (?, ?) order by regexp_replace(Title, \'^(A|An|The)\\\s\', \'\') asc', [$userId, Enums\ProjectStatusType::InProgress, Enums\ProjectStatusType::Stalled], Project::class); return Db::MultiTableSelect('SELECT * from Projects inner join Ebooks on Projects.EbookId = Ebooks.EbookId where ReviewerUserId = ? and Status in (?, ?) order by regexp_replace(Title, \'^(A|An|The)\\\s\', \'\') asc', [$userId, Enums\ProjectStatusType::InProgress, Enums\ProjectStatusType::Stalled], Project::class);
} }
/** /**
@ -686,7 +686,6 @@ final class Project{
$object = Project::FromRow($row['Projects']); $object = Project::FromRow($row['Projects']);
if($row['Projects']->EbookId !== null){ if($row['Projects']->EbookId !== null){
$row['Ebooks']->EbookId = $object->EbookId;
$object->Ebook = Ebook::FromRow($row['Ebooks']); $object->Ebook = Ebook::FromRow($row['Ebooks']);
} }