-
-
Notifications
You must be signed in to change notification settings - Fork 862
fix: prevent duplicate table name errors #3216
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
e5dd906
to
f643dcb
Compare
I will check failing test next week |
f643dcb
to
8e5e367
Compare
8e5e367
to
c8af15e
Compare
|
Hi @yajra, PR is now ready for review 🙏 |
The changes look good. Will hold off for now and review again in v12 (Laravel 12) release since there is a BC. Will try to complete the v12 within this or earlier next week. Thanks! |
@Seb33300 can you provide an example of the table aliases generated in this PR? One concern I have is the Oracle limitation that only accepts up to 30 chars for object/table name length. Initial Laravel 12 support merged on the master branch. Thanks! |
@yajra It concatenates all parent relation names to create a unique alias name:
Here is an example of query generated (on MySQL): select `users`.*
from `users`
left join `users` as `_updated_by` on `users`.`updated_user_id` = `_updated_by`.`id`
where `_updated_by`.`name` LIKE '%%seb%%'
order by `_updated_by`.`name` asc
limit 10
offset 0 |
Please note that starting Oracle Database 12c Release 2 (12.2) released in 2017, the maximum size is now 128 chars. And all Oracle versions prior that one are already no longer supported by Oracle: |
Yes, unfortunately - I still have projects that uses old Oracle version >.< |
Unless you have columns with multiple joins, It's unlikely to happen, but still theoretically possible. A workaround I can suggest is to use md5 to generate a hash of the alias in case it's more than 30 chars. |
Thanks and will review first on an actual project. I just recalled that we rarely use relation and opt to use join statements for more stable results. |
Tested on a new Laravel 12 app and works as expected. Tested self-join SQL and seems to be fixed: SQL Generated: select * from "users" left join "users" as "_creator" on "users"."created_by" = "_creator"."id" order by "_creator"."name" desc limit 10 offset 0
|
Yes, this is to prevent a potential conflict with a table name if the relation name is the same as the table name. |
Thanks for the feedback. Released on v12 🚀 |
That's not a small breaking change, every time we do a custom order we have to modify our code for example (not real code) :
we have to change it to :
please, find another way of doing it ? Plus, why keeping the leading |
Hi @Arkhas, yes the Also in #3229 we added a resolver to the |
having the column and the table as 2 seperate parameters would help :
but maybe we can have it as a configuration option ? we are struggling updating the package because of this commit :/ |
I will have a look on it tomorrow to see if I can improve by keeping backward compatibility |
@Arkhas I finally had time to take a look on this and it's unfortunately not possible to as backward compatibility. Even if we remove the front This is to support cases where we can join the same table multiple times such as:
Before, this was not working and resulted in an error. In order to help, I created a new PR to replace the DataTables::eloquent($model)
->orderColumn('item.total', function ($query, $order, $resolver) {
$query->orderBy(DB::raw("{$resolver('item.amount')} * {$resolver('item.quantity')}"), $order);
}); Can you please share your feedback on this? |
that would not help a lot, we would just need the table alias, (the name of the column is totally irrelevant as we are using a custom ordering. what would be nice:
but what we would need is to be able to not use this feature to not completely break our app like something like this :
or something like that |
The for example if you have a case where you need to get the tax rate from another table, using the resolver you can do: $resolver('item.amount') * $resolver('item.tax_rule.rate') The resolver can be used to resolve relations between models. And it automatically generate joins by preventing duplicate table aliases. I can try to implement a BC option as you suggested, but if that option is not enabled, you may face ambiguous column name errors. |
Another option you may use is to re create the join by yourself. $query->join('cart_items', ...) And then, you will be able to use the table name |
it would be easier for us to upgrade, maybe on a datatable basis instead of a global configuration so that we could upgrade slowly each of our Datatables :
something like that ? maybe more versatile |
Fixes #2871, #880 (maybe all issues with
Self Join
tag )This PR fixes the duplicate table name SQL error by adding aliases to joined tables.
It also supports multi levels joins:
Eg:
As you can see with the test case I modified, this PR comes with a small BC break.
If a column has defined a custom
order by
usingorderColumn()
, the table is now using an alias that will not match with the table name.A new parameter has been added to the
orderColumn()
callable to pass the column name with alias.