sql-parser icon indicating copy to clipboard operation
sql-parser copied to clipboard

Parser fails for updates that include subqueries for source tables

Open juacala opened this issue 5 years ago • 4 comments

The SQL Parser fails to parse the following query:

update `table1` as e, (select * from table2) e2
set
e.`id` = e2.id,
where e.id=e2.id

It returns the output below. This appears to always be an issue when using subqueries in the table references.

[
    {
        "tables": [
            {
                "database": null,
                "table": "table1",
                "column": null,
                "expr": "`table1`",
                "alias": "e",
                "function": null,
                "subquery": null
            }
        ],
        "set": null,
        "where": null,
        "order": null,
        "limit": null,
        "options": {
            "options": []
        },
        "first": 0,
        "last": 10
    },
    {
        "expr": [
            {
                "database": null,
                "table": null,
                "column": null,
                "expr": "*",
                "alias": null,
                "function": null,
                "subquery": null
            }
        ],
        "from": [
            {
                "database": null,
                "table": "table2",
                "column": null,
                "expr": "table2",
                "alias": null,
                "function": null,
                "subquery": null
            }
        ],
        "index_hints": null,
        "partition": null,
        "where": null,
        "group": null,
        "having": null,
        "order": null,
        "limit": null,
        "procedure": null,
        "into": null,
        "join": null,
        "union": [],
        "end_options": null,
        "options": {
            "options": []
        },
        "first": 11,
        "last": 21
    },
    {
        "options": {
            "options": []
        },
        "end_options": null,
        "set": [
            {
                "column": "e.`id`",
                "value": "e2.id"
            }
        ],
        "first": 22,
        "last": 44,
        "where": [
            {
                "identifiers": [
                    "e",
                    "id",
                    "e2"
                ],
                "isOperator": false,
                "expr": "e.id=e2.id"
            }
        ]
    }
]

juacala avatar Nov 14 '19 00:11 juacala

@Tithugues can I have some help with this one? Can I ask your help on issues?

williamdes avatar Nov 14 '19 06:11 williamdes

@juacala , what does it mean that the parser "fails" please? Do you have an error? If not, what result do you expect?

Tithugues avatar Nov 23 '19 14:11 Tithugues

To clarify, below is the same output but using var_dump (together with the JSON above, they give you an idea of what is being output). The query being parsed is a single update statement, but it returns, separately, an incomplete update statement, a select and then a set statement.

array (size=3)
  0 => 
    object(PhpMyAdmin\SqlParser\Statements\UpdateStatement)[53]
      public 'tables' => 
        array (size=1)
          0 => 
            object(PhpMyAdmin\SqlParser\Components\Expression)[55]
              ...
      public 'set' => null
      public 'where' => null
      public 'order' => null
      public 'limit' => null
      public 'options' => 
        object(PhpMyAdmin\SqlParser\Components\OptionsArray)[54]
          public 'options' => 
            array (size=0)
              ...
      public 'first' => int 0
      public 'last' => int 12
  1 => 
    object(PhpMyAdmin\SqlParser\Statements\SelectStatement)[59]
      public 'expr' => 
        array (size=1)
          0 => 
            object(PhpMyAdmin\SqlParser\Components\Expression)[61]
              ...
      public 'from' => 
        array (size=1)
          0 => 
            object(PhpMyAdmin\SqlParser\Components\Expression)[62]
              ...
      public 'index_hints' => null
      public 'partition' => null
      public 'where' => null
      public 'group' => null
      public 'having' => null
      public 'order' => null
      public 'limit' => null
      public 'procedure' => null
      public 'into' => null
      public 'join' => null
      public 'union' => 
        array (size=0)
          empty
      public 'end_options' => null
      public 'options' => 
        object(PhpMyAdmin\SqlParser\Components\OptionsArray)[60]
          public 'options' => 
            array (size=0)
              ...
      public 'first' => int 13
      public 'last' => int 23
  2 => 
    object(PhpMyAdmin\SqlParser\Statements\SetStatement)[66]
      public 'options' => 
        object(PhpMyAdmin\SqlParser\Components\OptionsArray)[67]
          public 'options' => 
            array (size=0)
              ...
      public 'end_options' => null
      public 'set' => 
        array (size=1)
          0 => 
            object(PhpMyAdmin\SqlParser\Components\SetOperation)[68]
              ...
      public 'first' => int 24
      public 'last' => int 46
      public 'where' => 
        array (size=1)
          0 => 
            object(PhpMyAdmin\SqlParser\Components\Condition)[69]
              ...

Perhaps I'm confused as to what I should expect, but I would have expected a single Update object that has the subquery as one of the source tables. Something liike:

[
    {
        "tables": [
            {
                "database": "db",
                "table": "table1",
                "column": null,
                "expr": "db.`table1`",
                "alias": "e",
                "function": null,
                "subquery": null
            },
            {
                "database": null,
                "table": "table2",
                "column": null,
                "expr": "?",
                "alias": "e2",
                "function": null,
                "subquery": "select * from table2"
            }
        ],
        "set": [
            {
                "column": "e.`id`",
                "value": "e2.id"
            }
        ],
        "where": [
            {
                "identifiers": [
                    "e",
                    "id",
                    "e2"
                ],
                "isOperator": false,
                "expr": "e.id=e2.id"
            }
        ],
        "order": null,
        "limit": null,
        "options": {
            "options": []
        },
        "first": 0,
        "last": 38
    }
]

juacala avatar Dec 05 '19 19:12 juacala