feat: add Query Builder whereColumn methods#10150
feat: add Query Builder whereColumn methods#10150memleakd wants to merge 4 commits intocodeigniter4:4.8from
Conversation
- Add whereColumn() and orWhereColumn() for column-to-column comparisons - Protect compared identifiers by default and support explicit unescaped usage - Document supported operators and invalid argument behavior - Add Query Builder, prefix, Model PHPDoc, user guide, and changelog coverage Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
michalsn
left a comment
There was a problem hiding this comment.
I like the idea, but I'm not particularly a fan of the implementation. And that's because of the $operator. The existing builder style puts the operator in the first argument, and if we create precedence here, some people may expect this is how it works everywhere.
To be fair, if I were designing this from scratch, I would probably prefer a separate operator parameter. But that is not the convention CodeIgniter has established, and I do not think this is the right place to introduce that inconsistency.
Also, in the current implementation, there is no way to distinguish "second column" from "operator with missing third argument", so whereColumn('created_at', '>=') becomes WHERE "created_at" = ">=".
|
That makes sense. I agree that even if a separate operator parameter is nice in isolation, it is inconsistent with existing convention. I’ll refactor this to parse the operator from the first argument, e.g. |
- Parse comparison operators from the first column argument - Reject ambiguous operator-as-second-column usage - Update docs, examples, tests, and Model PHPDoc - Keep operator parsing local to avoid changing existing where/having behavior Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
|
Thanks for the review and direction. I pushed a refactor that aligns the API with the existing Query Builder convention and also updated the PR body. |
datamweb
left a comment
There was a problem hiding this comment.
Thank you for refactoring the code! I find the changes very useful and appreciate your effort.
- Treat the second argument as a normal column identifier - Limit first-argument operator detection to terminal operators - Add regression tests for identifier and expression edge cases - Update docs for the refined validation behavior Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
- Detect only supported terminal comparison operators - Default to equality when no supported operator is found - Remove unsupported-operator validation - Update tests and docs for the simpler behavior Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
Description
This PR proposes adding
whereColumn()andorWhereColumn()to the Query Builder for comparing one column to another column without dropping down to raw SQL.This improves Query Builder DX for a common SQL pattern and reduces the need for manually written raw conditions like
where('created_at < updated_at'). It also keeps the comparison inside the framework’s identifier-protection flow instead of asking users to handle that manually.This is useful for common column-comparison queries while keeping the existing Query Builder behavior around identifier protection. The API follows the existing Query Builder convention of placing the operator in the first argument. If no operator is provided,
=is used. Column names are protected by default, and$escape = falseremains available for advanced cases such as SQL functions.Supported operators are
=,!=,<>,<,>,<=, and>=. Empty column names, unsupported operators, or ambiguous calls likewhereColumn('created_at', '>=')throw anInvalidArgumentException.Implementation note
This PR keeps the operator parsing local to
whereColumn()so it does not change the long-standing behavior ofwhere()/having(). There may be a future internal refactor opportunity to share operator parsing more broadly, but that is intentionally out of scope here to keep this PR focused and low-risk.Changes
whereColumn()andorWhereColumn()toBaseBuilder.OR, grouping, alias/prefix protection, unescaped expressions, invalid columns, invalid operators, and ambiguous operator-as-second-column usage.Checklist: