[10.x] Add toRawSql, dumpRawSql() and ddRawSql() to Query Builders #1
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
For quite some time, many developers have requested to get SQL queries with merged bindings from the query builder (laravel#38027, laravel#39053, laravel#39551, laravel#45705, laravel#45189).
They want to have something like this:
Instead of:
Prior Implementations
All prior implementations had the same issues that prevented them from being merged:
->whereRaw("description = 'foo?'")
Improved Implementation
These new ways of generating SQL queries with embedded bindings are available:
1. SQL Injections
I've built an extension for the database layer that can escape any values for safe embedding into SQL queries (laravel#46558) that is already merged into Laravel 10.x. Based on that code, any binding is escaped before being injected into the SQL query:
2. Ambiguous Question Marks
Simple search-and-replace operations are not enough to reliably generate a raw SQL statement. With raw expressions anyone can embed more question marks into a SQL query that are clearly no placeholders:
But this can also be solved relatively easily. The generated SQL string with placeholders is parsed by a very simple
LL(1)
parser (just 20 lines) to watch for string escape sequences and only replace question not being escaped in string literals:'
starts a string literal -> no question marks will be replaced''
and\'
marks escaped quotes -> they are copied'
ends a string literal -> question marks will be replaced again.That way the generated raw SQL string have no problem with question marks in string literals:
3. Executability of Raw SQL Queries
A generated query by these new functions should be able to be copied and pasted into any query tool and execute without problems. This is guaranteed for any database except PostgreSQL. Because PostgreSQL has special operators involving a question that needs to be doubled because of some PDO behaviour:
The query can not be executed as Laravel (correctly!) doubles the question mark (double ones are exempt from replacement 😉). To also make these special queries copy-able any (1) PostgreSQL operator containing a question mark that is (2) included in Laravel's operator information is decoded again:
Final
This implementation solves any known problems of generating raw SQL string known until today (including mine added for PostgreSQL).
I am open to a different naming for these new methods.