-
-
Notifications
You must be signed in to change notification settings - Fork 825
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
CRM_Utils_SQL_* - Properly interpolate NULL values #14250
Conversation
Overview -------- The `CRM_Utils_SQL_*` classes are used to generate SQL expressions with properly escaped data. However, in many cases, the values of `NULL` are processed in a way which clearly doesn't work, e.g. Before ------ When passing in a parameter with a `NULL` value, the parameter *is not evaluated at all*. ``` >>> CRM_Utils_SQL_Select::from('civicrm_contact')->where('do_not_email IS @foo', ['foo' => NULL])->toSQL() => """ SELECT *\n FROM civicrm_contact\n WHERE (do_not_email IS @foo)\n """ ``` Specifically: * `CRM_Utils_SQL_Select` - PHP NULL parameters are ignored (as if the value does not exist). No test coverage. * `CRM_Utils_SQL_Delete` - PHP NULL parameters are ignored (as if the value does not exist). No test coverage. * `CRM_Utils_SQL_Insert` - PHP NULL inputs are represented as SQL NULLs. No test coverage. After ----- When passing in a parameter with a PHP `NULL` value, the parameter is encoded as a SQL `NULL` value. ``` >>> CRM_Utils_SQL_Select::from('civicrm_contact')->where('do_not_email IS @foo', ['foo' => NULL])->toSQL() => """ SELECT *\n FROM civicrm_contact\n WHERE (do_not_email IS NULL)\n """ ``` Specifically: * `CRM_Utils_SQL_Select` - PHP NULL inputs are represented as SQL NULLs. Has test coverage. * `CRM_Utils_SQL_Delete` - PHP NULL inputs are represented as SQL NULLs. Has test coverage. * `CRM_Utils_SQL_Insert` - PHP NULL inputs are represented as SQL NULLs. Has test coverage. Comment ------- I'm generally hesitant about changing behavior like this. However, given that the old behavior was clearly non-functional, I'm struggling to figure a way where this would be problematic. Moreover, I'm a bit encouraged by the fact that: * There are unit-tests specifically for these classes, * When grepping core for references to `CRM_Utils_SQL_ `, there are several matches involving APIv3 and ActionSchedules -- both of which have a long practice of unit-testing. * When grepping my local ext's, there are several matches for things in `apiv4` and `civicase` - which also some test-coverage.
(Standard links)
|
Jenkins test this please |
One potential gotcha is that both Api3 and Api4 get actions are built on top of |
Yup, that's what I'd expect -- if it tried to pass down a NULL param and do a substitution on it, then the query would look nonsensical (like |
It would be appropriate to support WHERE (mytextfield IS NULL) as well as WHERE (mytextfield IS NOT NULL) in the API. Once this PR is merged, could that limitation be removed? |
@JoeMurray the api can do that already by doing something like
|
@colemanw is this mergeable - I saw you'd looked at it so haven't dug in myself |
Overview
The
CRM_Utils_SQL_*
classes are used to generate SQL expressions withproperly escaped data. However, in many cases, the values of
NULL
areprocessed in a way which clearly doesn't work, e.g.
Before
When passing in a parameter with a
NULL
value, the parameter is not evaluated at all.Specifically:
CRM_Utils_SQL_Select
- PHP NULL parameters are ignored (as if the value does not exist). No test coverage.CRM_Utils_SQL_Delete
- PHP NULL parameters are ignored (as if the value does not exist). No test coverage.CRM_Utils_SQL_Insert
- PHP NULL inputs are represented as SQL NULLs. No test coverage.After
When passing in a parameter with a PHP
NULL
value, the parameter is encoded as a SQLNULL
value.Specifically:
CRM_Utils_SQL_Select
- PHP NULL inputs are represented as SQL NULLs. Has test coverage.CRM_Utils_SQL_Delete
- PHP NULL inputs are represented as SQL NULLs. Has test coverage.CRM_Utils_SQL_Insert
- PHP NULL inputs are represented as SQL NULLs. Has test coverage.Comment
I'm generally hesitant about changing behavior like this. However, given
that the old behavior was clearly non-functional, I'm struggling to figure a
way where this would be problematic. Moreover, I'm a bit encouraged by the
fact that:
CRM_Utils_SQL_
, there are severalmatches involving APIv3 and ActionSchedules -- both of which have a long
practice of unit-testing.
apiv4
andcivicase
- which also some test-coverage.