Problem / motivation

SqlBase source plugin has the following configuration option:

  • ignore_map: (optional) Source data is joined to the map table by default. If set to TRUE, the map table will not be joined.

If the SQL query uses expressions, the ignore_map option must be set because expressions with aliases cannot be used with JOINs.

Proposed resolution

Document this to SqlBase source plugin API documentation.

Comments

masipila created an issue. See original summary.

heddn’s picture

masipila’s picture

Version: 8.6.x-dev » 8.5.x-dev
Status: Active » Needs review
StatusFileSize
new954 bytes

Thanks heddn for providing the SQL error message here so that if somebody is googling with the error message, they can find this issue.

Attached is a patch that adds this to API documentation.

Since this is documentation only, I'm proposing this to be cherry picked to 8.5.x.

Markus

heddn’s picture

Status: Needs review » Needs work

I want to work on the wording, but we should include why ignore map exists (slows performance, but improves SQL validity in certain cases). And we should point off to the SQL handbook if that works in the overall flow of things. On my phone, so I'll work on that later.

heddn’s picture

ignore_map: (optional) Source data is joined to the map table by default. If set to TRUE, the map table will not be joined. Set to FALSE if the sql has an expression added to it which will result in invalid SQL. Mapping helps speed up migration performance, but if it results in invalid SQL, then just disable it to retain valid SQL.

The conditional_expr used with ON is any conditional expression of the form that can be used in a WHERE clause.

https://dev.mysql.com/doc/refman/en/join.html

Standard SQL disallows references to column aliases in a WHERE clause. This restriction is imposed because when the WHERE clause is evaluated, the column value may not yet have been determined.

https://dev.mysql.com/doc/refman/en/problems-with-alias.html

An example of invalid query when ignore_map: true is set:

  public function query() {
    $query = $this->select('node', 'n')
      ->fields('n', ['nid']);
    // Add the value for the custom id.
    $query->addExpression(':now', 'current__date', [':now' => date('Ymd')]);
    return $query;
}
masipila’s picture

Hi,

Was your idea that we would add both those quotes to the actual docblock? There's no way to add quotes (blockquote tags) in the docblocks.

We should be able to explain this whole thing in a bit less verbose way. I'm not afraid of using lots of words to explain complex things but the amount of text we have in #5 is about the same as what we have for the database connection determination which is by far a bigger topic in this context.

So how about just this:
--clips--
ignore_map: (optional) Source data is joined to the map table by default to improve migration performance. If set to TRUE, the map table will not be joined. If the SQL query uses expressions (e.g. current date), the ignore_map option must be set to TRUE because expressions with aliases will result in invalid SQL.
--clips--

Markus

heddn’s picture

I'm much more +1 on your version. I just wanted to get all the docs together in a single place so we have them as a reference.

ignore_map: (optional) Source data is joined to the map table by default to improve migration performance. If set to TRUE, the map table will not be joined. If the SQL query uses expressions, the ignore_map option must be set to TRUE because expressions result in column aliases in a JOIN clause; which is considered invalid SQL.
masipila’s picture

Status: Needs work » Needs review
StatusFileSize
new1.15 KB
new1.3 KB
heddn’s picture

This seems like additional clarity on the docs. +1 on RTBC, but I wrote good parts so I'll leave to someone else.

phenaproxima’s picture

I took a look at \Drupal\Core\Database\Query\Select and I think that we can make this even better. I do think we should document it, but we should also take advantage of Select::getExpressions() and automatically set ignore_map to TRUE if there are any expressions attached to the query. Then we can simply document that behavior.

Something like this might work:

$ignore_map = (bool) $query->getExpressions();
heddn’s picture

I feel like someone could write an addExpression() query that results in valid SQL in a JOIN. I'm not sure how to articulate that thought without making it so techno-bable and conditional that it has zero meaning.

heddn’s picture

I did some digging, and it does seem possible. The other tricky thing, this whole thing is only important if the value in the expression is also part of the source id in getIds(). If it isn't part of the IDs, then it doesn't matter about the ignore_map.

    $query = $this->select('node', 'n')
      ->fields('n', ['nid']);
    // Add the value for the custom id.
    $query->addExpression('n.uid'); // <= I think this is valid and won't blow up because it isn't a dynamic value and is joinable.
    return $query;
masipila’s picture

StatusFileSize
new1.13 KB

Hi,

I loved phenaproxima's suggestion in #10. However, if the expressions do not *always* result into invalid SQL as pointed out by @heddn, then the documentation should be sufficient and trying to automatically detect this goes quite complex compared to the benefit.

Please find attached a new patch which tries to describe the situation with the latest information. Interdiff doesn't add too much value since we are talking about the whole sentence here.

Markus

heddn’s picture

Status: Needs review » Reviewed & tested by the community

I think this is closer what I'd want to say. We have the key words in there of invalid SQL and joins. So hopefully if someone runs into invalid SQL on the join, they can figure out to try setting ignore_map to true.

Since none of the wording is really at all what I wrote, I think I can now mark RTBC.

phenaproxima’s picture

Status: Reviewed & tested by the community » Needs work

One tiny thing, then +1 to RTBC.

+++ b/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php
@@ -24,8 +24,11 @@
+ *   joined. Using expressions in the query may result in column aliases in JOIN

Should be "...column aliases in the JOIN clause..."

masipila’s picture

Status: Needs work » Needs review
StatusFileSize
new1.14 KB
new1.02 KB

This should do it.

heddn’s picture

Status: Needs review » Reviewed & tested by the community
alexpott’s picture

Status: Reviewed & tested by the community » Patch (to be ported)

Committed 1b87d95 and pushed to 8.6.x. Thanks!

Leaving to port to 8.5.x

  • alexpott committed 1b87d95 on 8.6.x
    Issue #2949378 by masipila, heddn, phenaproxima: Document that SqlBase...
alexpott’s picture

Status: Patch (to be ported) » Fixed

Committed f073033 and pushed to 8.5.x. Thanks!

  • alexpott committed 146e1f5 on 8.5.x
    Issue #2949378 by masipila, heddn, phenaproxima: Document that SqlBase...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.