# outer and inner subquery match different types
"select id from user where id = 1 and user.col in (select user_extra.col from user_extra where user_extra.user_id = :a)"
"unsupported: subquery and parent route to different shards"

# join on having clause
"select e.col, u.id uid, e.id eid from user u join user_extra e having uid = eid"
{
  "Original": "select e.col, u.id uid, e.id eid from user u join user_extra e having uid = eid",
  "Instructions": {
    "Opcode": "Join",
    "Left": {
      "Opcode": "SelectScatter",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select u.id as uid from user as u",
      "FieldQuery": "select u.id as uid from user as u where 1 != 1"
    },
    "Right": {
      "Opcode": "SelectScatter",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select e.col, e.id as eid from user_extra as e having eid = :uid",
      "FieldQuery": "select e.col, e.id as eid from user_extra as e where 1 != 1",
      "JoinVars": {
        "uid": {}
      }
    },
    "Cols": [
      1,
      -1,
      2
    ],
    "Vars": {
      "uid": 0
    }
  }
}

# bind var already in use
"select e.col, u.id uid, e.id eid from user u join user_extra e having uid = eid and e.col = :uid"
{
  "Original": "select e.col, u.id uid, e.id eid from user u join user_extra e having uid = eid and e.col = :uid",
  "Instructions": {
    "Opcode": "Join",
    "Left": {
      "Opcode": "SelectScatter",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select u.id as uid from user as u",
      "FieldQuery": "select u.id as uid from user as u where 1 != 1"
    },
    "Right": {
      "Opcode": "SelectScatter",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select e.col, e.id as eid from user_extra as e having eid = :uid1 and e.col = :uid",
      "FieldQuery": "select e.col, e.id as eid from user_extra as e where 1 != 1",
      "JoinVars": {
        "uid1": {}
      }
    },
    "Cols": [
      1,
      -1,
      2
    ],
    "Vars": {
      "uid1": 0
    }
  }
}

# wire-up join with join, going left
"select u1.id from user u1 join user u2 join user u3 where u3.col = u1.col"
{
  "Original": "select u1.id from user u1 join user u2 join user u3 where u3.col = u1.col",
  "Instructions": {
    "Opcode": "Join",
    "Left": {
      "Opcode": "Join",
      "Left": {
        "Opcode": "SelectScatter",
        "Keyspace": {
          "Name": "user",
          "Sharded": true
        },
        "Query": "select u1.id, u1.col from user as u1",
        "FieldQuery": "select u1.id, u1.col from user as u1 where 1 != 1"
      },
      "Right": {
        "Opcode": "SelectScatter",
        "Keyspace": {
          "Name": "user",
          "Sharded": true
        },
        "Query": "select 1 from user as u2",
        "FieldQuery": "select 1 from user as u2 where 1 != 1"
      },
      "Cols": [
        -1,
        -2
      ]
    },
    "Right": {
      "Opcode": "SelectScatter",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select 1 from user as u3 where u3.col = :u1_col",
      "FieldQuery": "select 1 from user as u3 where 1 != 1",
      "JoinVars": {
        "u1_col": {}
      }
    },
    "Cols": [
      -1
    ],
    "Vars": {
      "u1_col": 1
    }
  }
}

# wire-up join with join, going left, then right
"select u1.id from user u1 join user u2 join user u3 where u3.col = u2.col"
{
  "Original": "select u1.id from user u1 join user u2 join user u3 where u3.col = u2.col",
  "Instructions": {
    "Opcode": "Join",
    "Left": {
      "Opcode": "Join",
      "Left": {
        "Opcode": "SelectScatter",
        "Keyspace": {
          "Name": "user",
          "Sharded": true
        },
        "Query": "select u1.id from user as u1",
        "FieldQuery": "select u1.id from user as u1 where 1 != 1"
      },
      "Right": {
        "Opcode": "SelectScatter",
        "Keyspace": {
          "Name": "user",
          "Sharded": true
        },
        "Query": "select u2.col from user as u2",
        "FieldQuery": "select u2.col from user as u2 where 1 != 1"
      },
      "Cols": [
        -1,
        1
      ]
    },
    "Right": {
      "Opcode": "SelectScatter",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select 1 from user as u3 where u3.col = :u2_col",
      "FieldQuery": "select 1 from user as u3 where 1 != 1",
      "JoinVars": {
        "u2_col": {}
      }
    },
    "Cols": [
      -1
    ],
    "Vars": {
      "u2_col": 1
    }
  }
}

# wire-up join with join, reuse existing result from a lower join
"select u1.id from user u1 join user u2 on u2.col = u1.col join user u3 where u3.col = u1.col"
{
  "Original": "select u1.id from user u1 join user u2 on u2.col = u1.col join user u3 where u3.col = u1.col",
  "Instructions": {
    "Opcode": "Join",
    "Left": {
      "Opcode": "Join",
      "Left": {
        "Opcode": "SelectScatter",
        "Keyspace": {
          "Name": "user",
          "Sharded": true
        },
        "Query": "select u1.id, u1.col from user as u1",
        "FieldQuery": "select u1.id, u1.col from user as u1 where 1 != 1"
      },
      "Right": {
        "Opcode": "SelectScatter",
        "Keyspace": {
          "Name": "user",
          "Sharded": true
        },
        "Query": "select 1 from user as u2 where u2.col = :u1_col",
        "FieldQuery": "select 1 from user as u2 where 1 != 1",
        "JoinVars": {
          "u1_col": {}
        }
      },
      "Cols": [
        -1,
        -2
      ],
      "Vars": {
        "u1_col": 1
      }
    },
    "Right": {
      "Opcode": "SelectScatter",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select 1 from user as u3 where u3.col = :u1_col",
      "FieldQuery": "select 1 from user as u3 where 1 != 1",
      "JoinVars": {
        "u1_col": {}
      }
    },
    "Cols": [
      -1
    ],
    "Vars": {
      "u1_col": 1
    }
  }
}

# wire-up join with join, reuse existing result from a lower join.
# You need two levels of join nesting to test this: when u3 requests
# col from u1, the u1-u2 joins exports the column to u2-u3. When
# u4 requests it, it should be reused from the u1-u2 join.
"select u1.id from user u1 join user u2 join user u3 on u3.id = u1.col join user u4 where u4.col = u1.col"
{
  "Original": "select u1.id from user u1 join user u2 join user u3 on u3.id = u1.col join user u4 where u4.col = u1.col",
  "Instructions": {
    "Opcode": "Join",
    "Left": {
      "Opcode": "Join",
      "Left": {
        "Opcode": "Join",
        "Left": {
          "Opcode": "SelectScatter",
          "Keyspace": {
            "Name": "user",
            "Sharded": true
          },
          "Query": "select u1.id, u1.col from user as u1",
          "FieldQuery": "select u1.id, u1.col from user as u1 where 1 != 1"
        },
        "Right": {
          "Opcode": "SelectScatter",
          "Keyspace": {
            "Name": "user",
            "Sharded": true
          },
          "Query": "select 1 from user as u2",
          "FieldQuery": "select 1 from user as u2 where 1 != 1"
        },
        "Cols": [
          -1,
          -2
        ]
      },
      "Right": {
        "Opcode": "SelectEqualUnique",
        "Keyspace": {
          "Name": "user",
          "Sharded": true
        },
        "Query": "select 1 from user as u3 where u3.id = :u1_col",
        "FieldQuery": "select 1 from user as u3 where 1 != 1",
        "Vindex": "user_index",
        "Values": ":u1_col",
        "JoinVars": {
          "u1_col": {}
        }
      },
      "Cols": [
        -1,
        -2
      ],
      "Vars": {
        "u1_col": 1
      }
    },
    "Right": {
      "Opcode": "SelectScatter",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select 1 from user as u4 where u4.col = :u1_col",
      "FieldQuery": "select 1 from user as u4 where 1 != 1",
      "JoinVars": {
        "u1_col": {}
      }
    },
    "Cols": [
      -1
    ],
    "Vars": {
      "u1_col": 1
    }
  }
}

# Test reuse of join var already being supplied to the right of a node.
"select u1.id from user u1 join (user u2 join user u3) where u2.id = u1.col and u3.id = u1.col"
{
  "Original": "select u1.id from user u1 join (user u2 join user u3) where u2.id = u1.col and u3.id = u1.col",
  "Instructions": {
    "Opcode": "Join",
    "Left": {
      "Opcode": "SelectScatter",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select u1.id, u1.col from user as u1",
      "FieldQuery": "select u1.id, u1.col from user as u1 where 1 != 1"
    },
    "Right": {
      "Opcode": "Join",
      "Left": {
        "Opcode": "SelectEqualUnique",
        "Keyspace": {
          "Name": "user",
          "Sharded": true
        },
        "Query": "select 1 from user as u2 where u2.id = :u1_col",
        "FieldQuery": "select 1 from user as u2 where 1 != 1",
        "Vindex": "user_index",
        "Values": ":u1_col",
        "JoinVars": {
          "u1_col": {}
        }
      },
      "Right": {
        "Opcode": "SelectEqualUnique",
        "Keyspace": {
          "Name": "user",
          "Sharded": true
        },
        "Query": "select 1 from user as u3 where u3.id = :u1_col",
        "FieldQuery": "select 1 from user as u3 where 1 != 1",
        "Vindex": "user_index",
        "Values": ":u1_col",
        "JoinVars": {
          "u1_col": {}
        }
      }
    },
    "Cols": [
      -1
    ],
    "Vars": {
      "u1_col": 1
    }
  }
}

# Join on weird columns.
"select `weird``name`.a, unsharded.b from `weird``name` join unsharded on `weird``name`.`a``b*c` = unsharded.id"
{
  "Original": "select `weird``name`.a, unsharded.b from `weird``name` join unsharded on `weird``name`.`a``b*c` = unsharded.id",
  "Instructions": {
    "Opcode": "Join",
    "Left": {
      "Opcode": "SelectScatter",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select `weird``name`.a, `weird``name`.`a``b*c` from `weird``name`",
      "FieldQuery": "select `weird``name`.a, `weird``name`.`a``b*c` from `weird``name` where 1 != 1"
    },
    "Right": {
      "Opcode": "SelectUnsharded",
      "Keyspace": {
        "Name": "main",
        "Sharded": false
      },
      "Query": "select unsharded.b from unsharded where unsharded.id = :weird_name_a_b_c",
      "FieldQuery": "select unsharded.b from unsharded where 1 != 1",
      "JoinVars": {
        "weird_name_a_b_c": {}
      }
    },
    "Cols": [
      -1,
      1
    ],
    "Vars": {
      "weird_name_a_b_c": 1
    }
  }
}

# Join on weird column (col is not in select)
"select unsharded.b from `weird``name` join unsharded on `weird``name`.`a``b*c` = unsharded.id"
{
  "Original": "select unsharded.b from `weird``name` join unsharded on `weird``name`.`a``b*c` = unsharded.id",
  "Instructions": {
    "Opcode": "Join",
    "Left": {
      "Opcode": "SelectScatter",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select `weird``name`.`a``b*c` from `weird``name`",
      "FieldQuery": "select `weird``name`.`a``b*c` from `weird``name` where 1 != 1"
    },
    "Right": {
      "Opcode": "SelectUnsharded",
      "Keyspace": {
        "Name": "main",
        "Sharded": false
      },
      "Query": "select unsharded.b from unsharded where unsharded.id = :weird_name_a_b_c",
      "FieldQuery": "select unsharded.b from unsharded where 1 != 1",
      "JoinVars": {
        "weird_name_a_b_c": {}
      }
    },
    "Cols": [
      1
    ],
    "Vars": {
      "weird_name_a_b_c": 0
    }
  }
}

# Invalid value in IN clause
"select id from user where id in (18446744073709551616, 1)"
"strconv.ParseUint: parsing "18446744073709551616": value out of range"

# Invalid value in IN clause from LHS of join
"select u1.id from user u1 join user u2 where u1.id = 18446744073709551616"
"strconv.ParseUint: parsing "18446744073709551616": value out of range"

# Invalid value in IN clause from RHS of join
"select u1.id from user u1 join user u2 where u2.id = 18446744073709551616"
"strconv.ParseUint: parsing "18446744073709551616": value out of range"
