-
-
Notifications
You must be signed in to change notification settings - Fork 2
Description
I've added SQL Server to the test workflow, and I get stuck on this issue. So I'm sharing in case someone as an idea and because writing things down sometimes helps me figure things out.
1) UserFrosting\Sprinkle\Core\Tests\Integration\Database\DatabaseTests::testBelongsToManyThroughPaginatedWithOrderByAggregateColumn
Illuminate\Database\QueryException: SQLSTATE[HY000]: General error: 20018 Column 'permissions.slug' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. [20018] (severity 16) [select top 1 [permissions].*, (select count(*) from [roles] inner join [permission_roles] on [roles].[id] = [permission_roles].[role_id] where [permissions].[id] = [permission_roles].[permission_id]) as [roles_count], [permissions].[id] from [permissions] inner join [permission_roles] on [permissions].[id] = [permission_roles].[permission_id] inner join [role_users] on [role_users].[role_id] = [permission_roles].[role_id] where [user_id] = 1 group by [permissions].[id] order by [roles_count] desc] (SQL: select top 1 [permissions].*, (select count(*) from [roles] inner join [permission_roles] on [roles].[id] = [permission_roles].[role_id] where [permissions].[id] = [permission_roles].[permission_id]) as [roles_count], [permissions].[id] from [permissions] inner join [permission_roles] on [permissions].[id] = [permission_roles].[permission_id] inner join [role_users] on [role_users].[role_id] = [permission_roles].[role_id] where [user_id] = 1 group by [permissions].[id] order by [roles_count] desc)
~/userfrosting/sprinkle-core/vendor/illuminate/database/Connection.php:712
~/userfrosting/sprinkle-core/vendor/illuminate/database/Connection.php:672
~/userfrosting/sprinkle-core/vendor/illuminate/database/Connection.php:376
~/userfrosting/sprinkle-core/vendor/illuminate/database/Query/Builder.php:2414
~/userfrosting/sprinkle-core/app/src/Database/Builder.php:115
~/userfrosting/sprinkle-core/vendor/illuminate/database/Eloquent/Builder.php:625
~/userfrosting/sprinkle-core/vendor/illuminate/database/Eloquent/Builder.php:609
~/userfrosting/sprinkle-core/app/src/Database/Relations/Concerns/Unique.php:300
~/userfrosting/sprinkle-core/app/src/Database/Relations/Concerns/Unique.php:340
~/userfrosting/sprinkle-core/app/src/Database/Relations/Concerns/Unique.php:250
~/userfrosting/sprinkle-core/app/tests/Integration/Database/DatabaseTests.php:750
Actual problem is this: https://stackoverflow.com/a/13999903/445757
It doesn't affect MySQL because MySQL is smart enough to understand how to handle that (somehow). And it's a "fake" issue in our case, because they are really the same slug (same id).
The failed test is this one :
| $paginatedPermissions = $user->permissions()->withCount('roles')->orderBy('roles_count', 'desc')->take(1)->offset(0); |
But it's not the query that cause the error. The error is caused by this query :
| $modelIds = $constrainedBuilder->get()->pluck($primaryKeyName)->toArray(); |
Here's the "beautified" SQL:
SELECT
top 1 [permissions].*,
(
SELECT
count(*)
FROM
[roles]
INNER JOIN [permission_roles] ON [roles].[id] = [permission_roles].[role_id]
WHERE
[permissions].[id] = [permission_roles].[permission_id]) AS [roles_count], [permissions].[id]
FROM
[permissions]
INNER JOIN [permission_roles] ON [permissions].[id] = [permission_roles].[permission_id]
INNER JOIN [role_users] ON [role_users].[role_id] = [permission_roles].[role_id]
WHERE
[user_id] = 1
GROUP BY
[permissions].[id]
ORDER BY
[roles_count] DESC
Problematic part is this : [permissions].*,. Remove the wildcard, remove the slug from columns.
Failed Solution n° 1
We could replace all existing columns (except the required "id" for the group by):
| $subQuery->addSelect($relatedPivotKeyName) |
...but this removes roles_count and mess up the sort.
There's no way I know to remove * without removing the roles_count (or other user defined select).
Failed Solution n° 2
The issue is with GROUP BY, so we remove the group by right?
Here's the result without Group By and limit :
| role_count | id |
|---|---|
| 3 | 2 |
| 3 | 2 |
| 1 | 3 |
| 1 | 1 |
So it does work with Limit 1, but Limit 2 won't work (testBelongsToManyThroughPaginated test will fail in this case highlighting this).
Group could be done on the Collection, but this means Limit and Offset also needs to be done In the Collection. Would make the whole thing less efficient.
Failed Solution n° 3
DISTINCT instead of GROUP BY doesn't help too.
$uniqueIdScope = function (Builder $subQuery) use ($relatedPivotKeyName) {
$subQuery->addSelect($relatedPivotKeyName)
->distinct();
// ->groupBy($relatedPivotKeyName);
};
It does fix testBelongsToManyThroughPaginatedWithOrderByAggregateColumn, but it doesn't fix testBelongsToManyThroughPaginated:
SELECT
*
FROM ( SELECT DISTINCT
[permissions].[id],
row_number() OVER (ORDER BY (
SELECT
0)) AS row_num
FROM
[permissions]
INNER JOIN [permission_roles] ON [permissions].[id] = [permission_roles].[permission_id]
INNER JOIN [role_users] ON [role_users].[role_id] = [permission_roles].[role_id]
WHERE
[user_id] = 1) AS temp_table
WHERE
row_num BETWEEN 2 AND 3
ORDER BY
row_num
Which returns ID [2, 2] instead of [2, 3]
Original SQL :
SELECT
*
FROM (
SELECT
[permissions].[id],
row_number() OVER (ORDER BY (
SELECT
0)) AS row_num
FROM
[permissions]
INNER JOIN [permission_roles] ON [permissions].[id] = [permission_roles].[permission_id]
INNER JOIN [role_users] ON [role_users].[role_id] = [permission_roles].[role_id]
WHERE
[user_id] = 1
GROUP BY
[permissions].[id]) AS temp_table
WHERE
row_num BETWEEN 2 AND 3
ORDER BY
row_num
Other solutions
We could "Cheat" the test and force select only 'id' :
$paginatedPermissions = $user->permissions()
->select('id')
->withCount('roles')
->orderBy('roles_count', 'desc')
->take(1)
->offset(0);But slug is not part of the results anymore (and bug is still there).
So I'm bit stuck now. SQL Server doesn't support this
Linked Branch : https://github.com/userfrosting/sprinkle-core/tree/5.0-mssql
Other references:
Metadata
Metadata
Assignees
Labels
Type
Projects
Status