Skip to content
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

[8.x] Add toRawSql() method on the query builder #38027

Closed
wants to merge 4 commits into from

Conversation

therobfonz
Copy link

This feature came from the desire to debug queries by combining toSql() and getBindings() into a complete raw query string. This adds another helpful debugging method to the query builder and enables a user to easily copy a raw query directly into a database GUI without having to manually replace parameter bindings in the toSql() output.

Usage

Model::where('foo', 'bar')->where('baz', 1)->toRawSql()

// output
"select * from model where "foo" = 'bar' and "baz" = 1"

The method takes into consideration if a parameter is a string or integer and will wrap a string in single quotes accordingly.

public function toRawSql()
{
return array_reduce($this->getBindings(), function ($sql, $binding) {
return preg_replace('/\?/', is_numeric($binding) ? $binding : "'".$binding."'", $sql, 1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest to add null check and return a 'null' sql string. It may be important in insert/update query.

image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also there are $this->grammar->quoteString() or $this->connection->quote() for quoting value.

Copy link
Author

@therobfonz therobfonz Jul 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest to add null check and return a 'null' sql string. It may be important in insert/update query.

image

Since insert/update statement return a boolean, it's actually not possible to run toSql() or toRawSql() on those statements. Was there a particular way you were writing the statement where you had this scenario that might not work? Ran a few tests and any where('field', null) was already converted by toSql() to "field" is null.

@tpetry
Copy link
Contributor

tpetry commented Jul 16, 2021

Your code is missing edge cases because of PostgreSQL. In PostgreSQL there are multiple operators consisting of a questionmark (e.g. the jsonb operators). These parameters can be used in queries but the question mark needs to be escaped by another question mark. So the operator ? will be ?? and ?| will be ??|.
You need to replace questionmarks which have no leading or trailing question mark like i did here for tpetry/laravel-postgresql-enhanced. And null values should not be escaped because they are a special sql keyword. A condition like WHERE foo IS 'null' is not the same as WHERE foo IS null.

@taylorotwell
Copy link
Member

Thanks for your pull request to Laravel!

Unfortunately, I'm going to delay merging this code for now. To preserve our ability to adequately maintain the framework, we need to be very careful regarding the amount of code we include.

If possible, please consider releasing your code as a package so that the community can still take advantage of your contributions!

If you feel absolutely certain that this code corrects a bug in the framework, please "@" mention me in a follow-up comment with further explanation so that GitHub will send me a notification of your response.

@therobfonz
Copy link
Author

@taylorotwell Thanks! I have been using this as a macro and you have given us the ability to do that so no problem with closing this. Appreciate the feedback!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants