Skip to content

Bug: Method first() in model is forcing group by #6487

Description

@WillRy

PHP Version

8.1

CodeIgniter4 Version

4.2.0

CodeIgniter4 Installation Method

Composer (using codeigniter4/appstarter)

Which operating systems have you tested for this bug?

Linux

Which server did you use?

apache

Database

MySQL 8

What happened?

When making a query that has several "joins", bringing the fields from more than one table, the "first" method forces a group by in the primary key, in the CodeIgniter\Model class, in the doFirst() method, line 240:

$builder->groupBy($this->table . '.' . $this->primaryKey);

This generates a bug in almost all MySQL 8 installations, due to the installation coming with "only_full_group_by" mode enabled.

I believe that they should not force a group by unnecessarily, because this increases the cost of the query in some cases and also causes an error: only_full_group_by - mysqli_sql_exception

Here's an example of the error:

<?php
$attributes = [
    'products.*',

    'categories.id AS category_id',
    'categories.name AS category_name',
];

$ordem = $this
    ->select($attributes)
    ->join('categories_products', 'categories_products.product_id = products.id', "LEFT")
    ->join('categories', 'categories.id = categories_products.id', "LEFT")
    ->where('products.id', 1)
    ->withDeleted()
    ->first();

The error happens, because the only_full_group_by mode requires that all select fields are in group by, to avoid problems and bugs in aggregation. The first() method forces a group by on only one field, which is the primary key.

Thank you very much in advance

Steps to Reproduce

Execute a query with multiple joins, bringing data from more than one table in select, with the first() method.

IMPORTANT: Use MYSQL 8 in newer versions, with only_full_group_by enabled

<?php
$attributes = [
    'products.*',

    'categories.id AS category_id',
    'categories.name AS category_name',
];

$ordem = $this
    ->select($attributes)
    ->join('categories_products', 'categories_products.product_id = products.id', "LEFT")
    ->join('categories', 'categories.id = categories_products.id', "LEFT")
    ->where('products.id', 1)
    ->withDeleted()
    ->first();

Expected Output

Not having only_full_group_by errors and not making an unnecessary group by

The query that was generated was:

select
    products.*,
    categories.id AS category_id,
    categories.name AS category_name
FROM 
products
left join categories_products on categories_products.product_id = products.id
left join categories on categories.id = categories_products.category_id
where product.id = 1
group by product.id;

The query that should have been generated(without group by)

select
    products.*,
    categories.id AS category_id,
    categories.name AS category_name
FROM 
products
left join categories_products on categories_products.product_id = products.id
left join categories on categories.id = categories_products.category_id
where product.id = 1;

Anything else?

No response

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    databaseIssues or pull requests that affect the database layer

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions