Skip to content
This repository has been archived by the owner on Jul 15, 2021. It is now read-only.

Incorrect AST when using "LIKE" expression #47

Open
malolans-r7 opened this issue Jan 23, 2018 · 2 comments
Open

Incorrect AST when using "LIKE" expression #47

malolans-r7 opened this issue Jan 23, 2018 · 2 comments
Assignees
Labels

Comments

@malolans-r7
Copy link

When parsing a query like:

SELECT *
FROM Bees b
WHERE wings LIKE '1' AND limbs = 'blah'

The AST generated is incorrect.

{
  "type": "statement",
  "variant": "list",
  "statement": [
    {
      "type": "statement",
      "variant": "select",
      "result": [
        {
          "type": "identifier",
          "variant": "star",
          "name": "*"
        }
      ],
      "from": {
        "type": "identifier",
        "variant": "table",
        "name": "bees",
        "alias": "b"
      },
      "where": [
        {
          "type": "expression",
          "format": "binary",
          "variant": "operation",
          "operation": "like",
          "right": {
            "type": "expression",
            "format": "binary",
            "variant": "operation",
            "operation": "and",
            "left": {
              "type": "literal",
              "variant": "text",
              "value": "1"
            },
            "right": {
              "type": "expression",
              "format": "binary",
              "variant": "operation",
              "operation": "=",
              "left": {
                "type": "identifier",
                "variant": "column",
                "name": "limbs"
              },
              "right": {
                "type": "literal",
                "variant": "text",
                "value": "blah"
              }
            }
          },
          "left": {
            "type": "identifier",
            "variant": "column",
            "name": "wings"
          }
        }
      ]
    }
  ]
}

In the where clause, the LIKE node is the root node. However AND node should be the root node.

@nwronski nwronski self-assigned this Jan 29, 2018
@nwronski nwronski added the bug label Jan 29, 2018
@cisaacson
Copy link

I have confirmed this bug as well. Here is another more complex example with several operators, LIKE is the only one that sometimes puts a 'binary' 'and' between the 'left' and 'right'. It seems to be dependent on where the LIKE is in the order of statements too, if the LIKE expression is last it works fine. If you view the AST in a JSON viewer it is very easy to see the issue.

SELECT a, b
FROM x, y
WHERE d = 'X'
  AND e BETWEEN '1/1/2018' AND '1/31/2018'
  AND f != 'NEW'
  AND g >= 1000000
  AND (h IS NULL
  OR j IS NOT NULL)
  AND k LIKE 'Jones%'
  AND l IN ('CA', 'OR', 'NY')
{"type":"statement","variant":"list","statement":[{"type":"statement","variant":"select","result":[{"type":"identifier","variant":"column","name":"a"},{"type":"identifier","variant":"column","name":"b"}],"from":{"type":"map","variant":"join","source":{"type":"identifier","variant":"table","name":"x"},"map":[{"type":"join","variant":"cross join","source":{"type":"identifier","variant":"table","name":"y"}}]},"where":[{"type":"expression","format":"binary","variant":"operation","operation":"and","left":{"type":"expression","format":"binary","variant":"operation","operation":"and","left":{"type":"expression","format":"binary","variant":"operation","operation":"and","left":{"type":"expression","format":"binary","variant":"operation","operation":"and","left":{"type":"expression","format":"binary","variant":"operation","operation":"and","left":{"type":"expression","format":"binary","variant":"operation","operation":"=","left":{"type":"identifier","variant":"column","name":"d"},"right":{"type":"literal","variant":"text","value":"X"}},"right":{"type":"expression","format":"binary","variant":"operation","operation":"between","right":{"type":"expression","format":"binary","variant":"operation","operation":"and","left":{"type":"literal","variant":"text","value":"1/1/2018"},"right":{"type":"literal","variant":"text","value":"1/31/2018"}},"left":{"type":"identifier","variant":"column","name":"e"}}},"right":{"type":"expression","format":"binary","variant":"operation","operation":"!=","left":{"type":"identifier","variant":"column","name":"f"},"right":{"type":"literal","variant":"text","value":"NEW"}}},"right":{"type":"expression","format":"binary","variant":"operation","operation":">=","left":{"type":"identifier","variant":"column","name":"g"},"right":{"type":"literal","variant":"decimal","value":"1000000"}}},"right":{"type":"expression","format":"binary","variant":"operation","operation":"or","left":{"type":"expression","format":"binary","variant":"operation","operation":"is","left":{"type":"identifier","variant":"column","name":"h"},"right":{"type":"literal","variant":"null","value":"null"}},"right":{"type":"expression","format":"binary","variant":"operation","operation":"is not","left":{"type":"identifier","variant":"column","name":"j"},"right":{"type":"literal","variant":"null","value":"null"}}}},"right":{"type":"expression","format":"binary","variant":"operation","operation":"like","right":{"type":"expression","format":"binary","variant":"operation","operation":"and","left":{"type":"literal","variant":"text","value":"Jones%"},"right":{"type":"expression","format":"binary","variant":"operation","operation":"in","right":{"type":"expression","variant":"list","expression":[{"type":"literal","variant":"text","value":"CA"},{"type":"literal","variant":"text","value":"OR"},{"type":"literal","variant":"text","value":"NY"}]},"left":{"type":"identifier","variant":"column","name":"l"}}},"left":{"type":"identifier","variant":"column","name":"k"}}}]}]}

@eatonphil
Copy link

Here is another minimal example (just two like expressions joined with an and), first with parens (correct), second (wrong one) without parens:

> const { statement: [{ where: [where7] }] }  = parser("select 1 where (description like 'foo') and (description like 'bar')");
undefined
> where7
{ type: 'expression',
  format: 'binary',
  variant: 'operation',
  operation: 'and',
  left:
   { type: 'expression',
     format: 'binary',
     variant: 'operation',
     operation: 'like',
     right: { type: 'literal', variant: 'text', value: 'foo' },
     left: { type: 'identifier', variant: 'column', name: 'description' } },
  right:
   { type: 'expression',
     format: 'binary',
     variant: 'operation',
     operation: 'like',
     right: { type: 'literal', variant: 'text', value: 'bar' },
     left: { type: 'identifier', variant: 'column', name: 'description' } } }
> const { statement: [{ where: [where9] }] }  = parser("select 1 where description like 'foo' and description like 'bar'");
undefined
> where9
{ type: 'expression',
  format: 'binary',
  variant: 'operation',
  operation: 'like',
  right:
   { type: 'expression',
     format: 'binary',
     variant: 'operation',
     operation: 'and',
     left: { type: 'literal', variant: 'text', value: 'foo' },
     right:
      { type: 'expression',
        format: 'binary',
        variant: 'operation',
        operation: 'like',
        right: [Object],
        left: [Object] } },
  left: { type: 'identifier', variant: 'column', name: 'description' } }

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

No branches or pull requests

4 participants