# Group by with aggregation
"select col1, count(col2) as col2_count from unsharded group by col1 order by col2_count asc"
{
  "Original": "select col1, count(col2) as col2_count from unsharded group by col1 order by col2_count asc",
  "Instructions": {
    "Opcode": "SelectUnsharded",
    "Keyspace": {
      "Name": "main",
      "Sharded": false
    },
    "Query": "select col1, count(col2) as col2_count from unsharded group by col1 order by col2_count asc",
    "FieldQuery": "select col1, count(col2) as col2_count from unsharded where 1 != 1 group by col1"
  }
}
# Group by unsharded
"select col1, col2 from unsharded group by col2"
{
  "Original": "select col1, col2 from unsharded group by col2",
  "Instructions": {
    "Opcode": "SelectUnsharded",
    "Keyspace": {
      "Name": "main",
      "Sharded": false
    },
    "Query": "select col1, col2 from unsharded group by col2",
    "FieldQuery": "select col1, col2 from unsharded where 1 != 1 group by col2"
  }
}

# Group by on unique sharded
"select col1, col2 from user where id = 1 group by col2"
{
  "Original": "select col1, col2 from user where id = 1 group by col2",
  "Instructions": {
    "Opcode": "SelectEqualUnique",
    "Keyspace": {
      "Name": "user",
      "Sharded": true
    },
    "Query": "select col1, col2 from user where id = 1 group by col2",
    "FieldQuery": "select col1, col2 from user where 1 != 1 group by col2",
    "Vindex": "user_index",
    "Values": 1
  }
}

# Group by on unique vindex
"select col1, id from user group by id"
{
  "Original": "select col1, id from user group by id",
  "Instructions": {
    "Opcode": "SelectScatter",
    "Keyspace": {
      "Name": "user",
      "Sharded": true
    },
    "Query": "select col1, id from user group by id",
    "FieldQuery": "select col1, id from user where 1 != 1 group by id"
  }
}

# Group by implicitly references table col
"select id from user group by id, col"
{
  "Original": "select id from user group by id, col",
  "Instructions": {
    "Opcode": "SelectScatter",
    "Keyspace": {
      "Name": "user",
      "Sharded": true
    },
    "Query": "select id from user group by id, col",
    "FieldQuery": "select id from user where 1 != 1 group by id, col"
  }
}

# Group by references outer query
"select aa, id from user where id = 5 having id in (select u.id from user u join user_extra e on u.id = e.user_id where u.id = 5 group by aa)"
"symbol aa not found"

# HAVING implicitly references table col
"select user.col1 from user having col2 = 2"
{
  "Original": "select user.col1 from user having col2 = 2",
  "Instructions": {
    "Opcode": "SelectScatter",
    "Keyspace": {
      "Name": "user",
      "Sharded": true
    },
    "Query": "select user.col1 from user having col2 = 2",
    "FieldQuery": "select user.col1 from user where 1 != 1"
  }
}

# ambiguous symbol reference
"select user.col1, user_extra.col1 from user join user_extra having col1 = 2"
"ambiguous symbol reference: col1"

# non-ambiguous symbol reference
"select user.col1, user_extra.col1 from user join user_extra having user_extra.col1 = 2"
{
  "Original": "select user.col1, user_extra.col1 from user join user_extra having user_extra.col1 = 2",
  "Instructions": {
    "Opcode": "Join",
    "Left": {
      "Opcode": "SelectScatter",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select user.col1 from user",
      "FieldQuery": "select user.col1 from user where 1 != 1"
    },
    "Right": {
      "Opcode": "SelectScatter",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select user_extra.col1 from user_extra having user_extra.col1 = 2",
      "FieldQuery": "select user_extra.col1 from user_extra where 1 != 1"
    },
    "Cols": [
      -1,
      1
    ]
  }
}

# HAVING multi-route
"select user.col1 as a, user.col2, user_extra.col3 from user join user_extra having 1 = 1 and a = 1 and a = user.col2 and user_extra.col3 = 1"
{
  "Original": "select user.col1 as a, user.col2, user_extra.col3 from user join user_extra having 1 = 1 and a = 1 and a = user.col2 and user_extra.col3 = 1",
  "Instructions": {
    "Opcode": "Join",
    "Left": {
      "Opcode": "SelectScatter",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select user.col1 as a, user.col2 from user having 1 = 1 and a = 1 and a = user.col2",
      "FieldQuery": "select user.col1 as a, user.col2 from user where 1 != 1"
    },
    "Right": {
      "Opcode": "SelectScatter",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select user_extra.col3 from user_extra having user_extra.col3 = 1",
      "FieldQuery": "select user_extra.col3 from user_extra where 1 != 1"
    },
    "Cols": [
      -1,
      -2,
      1
    ]
  }
}

# Correlated subquery in having clause.
# We're testing to make sure that the inner 'id' finds the outer id of the select.
# The subquery query needs to be a join. Otherwise, unqualified references bind to the default inner table.
"select id, col from user having col in (select user_extra.col from user join user_extra on user.id = user_extra.user_id where user_extra.user_id = id)"
{
  "Original": "select id, col from user having col in (select user_extra.col from user join user_extra on user.id = user_extra.user_id where user_extra.user_id = id)",
  "Instructions": {
    "Opcode": "SelectScatter",
    "Keyspace": {
      "Name": "user",
      "Sharded": true
    },
    "Query": "select id, col from user having col in (select user_extra.col from user join user_extra on user.id = user_extra.user_id where user_extra.user_id = id)",
    "FieldQuery": "select id, col from user where 1 != 1"
  }
}

# Correlated subquery in having clause, subquery also has having clause. Not allowed
"select id, col from user having col in (select user_extra.col extra_col, user.id as user_id from user join user_extra on user.id = user_extra.user_id having user_id = id and extra_col = col)"
"symbol id not found"

# Correlated subquery in having clause, subquery also has having clause, even more rare case.
# We're looking for symbol not found error this time.
"select id, col from user having col in (select user_extra.col, user.id as user_id from user join user_extra on user.id = user_extra.user_id having user_id = notthere)"
"symbol notthere not found"

# ORDER BY, reference col from local table.
"select col from user where id = 5 order by aa"
{
  "Original": "select col from user where id = 5 order by aa",
  "Instructions": {
    "Opcode": "SelectEqualUnique",
    "Keyspace": {
      "Name": "user",
      "Sharded": true
    },
    "Query": "select col from user where id = 5 order by aa asc",
    "FieldQuery": "select col from user where 1 != 1",
    "Vindex": "user_index",
    "Values": 5
  }
}

# ORDER BY uses column numbers
"select col from user where id = 1 order by 1"
{
  "Original": "select col from user where id = 1 order by 1",
  "Instructions": {
    "Opcode": "SelectEqualUnique",
    "Keyspace": {
      "Name": "user",
      "Sharded": true
    },
    "Query": "select col from user where id = 1 order by 1 asc",
    "FieldQuery": "select col from user where 1 != 1",
    "Vindex": "user_index",
    "Values": 1
  }
}

# ORDER BY NULL
"select col from user order by null"
{
  "Original": "select col from user order by null",
  "Instructions": {
    "Opcode": "SelectScatter",
    "Keyspace": {
      "Name": "user",
      "Sharded": true
    },
    "Query": "select col from user order by null",
    "FieldQuery": "select col from user where 1 != 1"
  }
}

# ORDER BY for join
"select user.col1 as a, user.col2, music.col3 from user join music on user.id = music.id where user.id = 1 order by a asc, user.col2 desc, music.col3 asc"
{
  "Original": "select user.col1 as a, user.col2, music.col3 from user join music on user.id = music.id where user.id = 1 order by a asc, user.col2 desc, music.col3 asc",
  "Instructions": {
    "Opcode": "Join",
    "Left": {
      "Opcode": "SelectEqualUnique",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select user.col1 as a, user.col2, user.id from user where user.id = 1 order by a asc, user.col2 desc",
      "FieldQuery": "select user.col1 as a, user.col2, user.id from user where 1 != 1",
      "Vindex": "user_index",
      "Values": 1
    },
    "Right": {
      "Opcode": "SelectEqualUnique",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select music.col3 from music where music.id = :user_id order by music.col3 asc",
      "FieldQuery": "select music.col3 from music where 1 != 1",
      "Vindex": "music_user_map",
      "Values": ":user_id",
      "JoinVars": {
        "user_id": {}
      }
    },
    "Cols": [
      -1,
      -2,
      1
    ],
    "Vars": {
      "user_id": 2
    }
  }
}

# ORDER BY NULL for join
"select user.col1 as a, user.col2, music.col3 from user join music on user.id = music.id where user.id = 1 order by null"
{
  "Original": "select user.col1 as a, user.col2, music.col3 from user join music on user.id = music.id where user.id = 1 order by null",
  "Instructions": {
    "Opcode": "Join",
    "Left": {
      "Opcode": "SelectEqualUnique",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select user.col1 as a, user.col2, user.id from user where user.id = 1 order by null",
      "FieldQuery": "select user.col1 as a, user.col2, user.id from user where 1 != 1",
      "Vindex": "user_index",
      "Values": 1
    },
    "Right": {
      "Opcode": "SelectEqualUnique",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select music.col3 from music where music.id = :user_id order by null",
      "FieldQuery": "select music.col3 from music where 1 != 1",
      "Vindex": "music_user_map",
      "Values": ":user_id",
      "JoinVars": {
        "user_id": {}
      }
    },
    "Cols": [
      -1,
      -2,
      1
    ],
    "Vars": {
      "user_id": 2
    }
  }
}

# ORDER BY for join, using column numbers
"select user.col1 as a, user.col2, music.col3 from user join music on user.id = music.id where user.id = 1 order by 1 asc, 2 desc, 3 asc"
{
  "Original": "select user.col1 as a, user.col2, music.col3 from user join music on user.id = music.id where user.id = 1 order by 1 asc, 2 desc, 3 asc",
  "Instructions": {
    "Opcode": "Join",
    "Left": {
      "Opcode": "SelectEqualUnique",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select user.col1 as a, user.col2, user.id from user where user.id = 1 order by 1 asc, 2 desc",
      "FieldQuery": "select user.col1 as a, user.col2, user.id from user where 1 != 1",
      "Vindex": "user_index",
      "Values": 1
    },
    "Right": {
      "Opcode": "SelectEqualUnique",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select music.col3 from music where music.id = :user_id order by 1 asc",
      "FieldQuery": "select music.col3 from music where 1 != 1",
      "Vindex": "music_user_map",
      "Values": ":user_id",
      "JoinVars": {
        "user_id": {}
      }
    },
    "Cols": [
      -1,
      -2,
      1
    ],
    "Vars": {
      "user_id": 2
    }
  }
}

# Order by, '*' expression
"select * from user where id = 5 order by col"
{
  "Original": "select * from user where id = 5 order by col",
  "Instructions": {
    "Opcode": "SelectEqualUnique",
    "Keyspace": {
      "Name": "user",
      "Sharded": true
    },
    "Query": "select * from user where id = 5 order by col asc",
    "FieldQuery": "select * from user where 1 != 1",
    "Vindex": "user_index",
    "Values": 5
  }
}

# Order by, qualified '*' expression
"select user.* from user where id = 5 order by user.col"
{
  "Original": "select user.* from user where id = 5 order by user.col",
  "Instructions": {
    "Opcode": "SelectEqualUnique",
    "Keyspace": {
      "Name": "user",
      "Sharded": true
    },
    "Query": "select user.* from user where id = 5 order by user.col asc",
    "FieldQuery": "select user.* from user where 1 != 1",
    "Vindex": "user_index",
    "Values": 5
  }
}

# Order by, '*' expression with qualified reference
"select * from user where id = 5 order by user.col"
{
  "Original": "select * from user where id = 5 order by user.col",
  "Instructions": {
    "Opcode": "SelectEqualUnique",
    "Keyspace": {
      "Name": "user",
      "Sharded": true
    },
    "Query": "select * from user where id = 5 order by user.col asc",
    "FieldQuery": "select * from user where 1 != 1",
    "Vindex": "user_index",
    "Values": 5
  }
}

# Order by, '*' expression in a subquery
"select u.id, e.id from user u join user_extra e where u.col = e.col and u.col in (select * from user where user.id = u.id order by col)"
{
  "Original": "select u.id, e.id from user u join user_extra e where u.col = e.col and u.col in (select * from user where user.id = u.id order by col)",
  "Instructions": {
    "Opcode": "Join",
    "Left": {
      "Opcode": "SelectScatter",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select u.id, u.col from user as u where u.col in (select * from user where user.id = u.id order by col asc)",
      "FieldQuery": "select u.id, u.col from user as u where 1 != 1"
    },
    "Right": {
      "Opcode": "SelectScatter",
      "Keyspace": {
        "Name": "user",
        "Sharded": true
      },
      "Query": "select e.id from user_extra as e where e.col = :u_col",
      "FieldQuery": "select e.id from user_extra as e where 1 != 1",
      "JoinVars": {
        "u_col": {}
      }
    },
    "Cols": [
      -1,
      1
    ],
    "Vars": {
      "u_col": 1
    }
  }
}

# Order by references outer query
"select aa, id from user where id = 5 having id in (select u.id from user u join user_extra e on u.id = e.user_id where u.id = 5 order by aa)"
"symbol aa not found"

# Order by, verify outer symtab is searched according to its own context.
"select u.id from user u having u.id in (select col2 from user where user.id = u.id order by u.col)"
"symbol u.col not found"

# Order by, qualified '*' expression, name mismatched.
"select user.* from user where id = 5 order by e.col"
"symbol e.col not found"

# Order by, invalid column number
"select col from user order by 18446744073709551616"
"error parsing order by clause: 18446744073709551616"

# Order by, out of range column number
"select col from user order by 2"
"order by column number out of range"

# Order by, '*' expression with qualified reference and using collate
"select * from user where id = 5 order by user.col collate utf8_general_ci"
{
  "Original": "select * from user where id = 5 order by user.col collate utf8_general_ci",
  "Instructions": {
    "Opcode": "SelectEqualUnique",
    "Keyspace": {
      "Name": "user",
      "Sharded": true
    },
    "Query": "select * from user where id = 5 order by user.col collate utf8_general_ci asc",
    "FieldQuery": "select * from user where 1 != 1",
    "Vindex": "user_index",
    "Values": 5
  }
}

# Order by join qualified by collate operator
"select user.col1 as a, user_extra.col2 as b from user inner join user_extra on user_extra.user_id = 5 where user.id = 5 order by a collate utf8_general_ci, b collate utf8_general_ci"
{
   "Original":"select user.col1 as a, user_extra.col2 as b from user inner join user_extra on user_extra.user_id = 5 where user.id = 5 order by a collate utf8_general_ci, b collate utf8_general_ci",
   "Instructions":{
      "Opcode":"Join",
      "Left":{
         "Opcode":"SelectEqualUnique",
         "Keyspace":{
            "Name":"user",
            "Sharded":true
         },
         "Query":"select user.col1 as a from user where user.id = 5 order by a collate utf8_general_ci asc",
         "FieldQuery":"select user.col1 as a from user where 1 != 1",
         "Vindex":"user_index",
         "Values":5
      },
      "Right":{
         "Opcode":"SelectEqualUnique",
         "Keyspace":{
            "Name":"user",
            "Sharded":true
         },
         "Query":"select user_extra.col2 as b from user_extra where user_extra.user_id = 5 order by b collate utf8_general_ci asc",
         "FieldQuery":"select user_extra.col2 as b from user_extra where 1 != 1",
         "Vindex":"user_index",
         "Values":5
      },
      "Cols":[
         -1,
         1
      ]
   }
}

# Group by with collate operator
"select user.col1 as a from user where user.id = 5 group by a collate utf8_general_ci"
{
   "Original":"select user.col1 as a from user where user.id = 5 group by a collate utf8_general_ci",
   "Instructions":{
      "Opcode":"SelectEqualUnique",
      "Keyspace":{
         "Name":"user",
         "Sharded":true
      },
      "Query":"select user.col1 as a from user where user.id = 5 group by a collate utf8_general_ci",
      "FieldQuery":"select user.col1 as a from user where 1 != 1 group by a collate utf8_general_ci",
      "Vindex":"user_index",
      "Values":5
   }
}

#Order by with aggregates
"select * from user where id = 5 order by count(id)"
{
   "Original":"select * from user where id = 5 order by count(id)",
   "Instructions":{
      "Opcode":"SelectEqualUnique",
      "Keyspace":{
         "Name":"user",
         "Sharded":true
      },
      "Query":"select * from user where id = 5 order by count(id) asc",
      "FieldQuery":"select * from user where 1 != 1",
      "Vindex":"user_index",
      "Values":5
   }
}

#Order by with math functions
"select * from user where id = 5 order by -col1"
{
   "Original":"select * from user where id = 5 order by -col1",
   "Instructions":{
      "Opcode":"SelectEqualUnique",
      "Keyspace":{
         "Name":"user",
         "Sharded":true
      },
      "Query":"select * from user where id = 5 order by -col1 asc",
      "FieldQuery":"select * from user where 1 != 1",
      "Vindex":"user_index",
      "Values":5
   }
}

#Order by with string operations operations
"select * from user where id = 5 order by concat(col,col1) collate utf8_general_ci desc"
{
   "Original":"select * from user where id = 5 order by concat(col,col1) collate utf8_general_ci desc",
   "Instructions":{
      "Opcode":"SelectEqualUnique",
      "Keyspace":{
         "Name":"user",
         "Sharded":true
      },
      "Query":"select * from user where id = 5 order by concat(col, col1) collate utf8_general_ci desc",
      "FieldQuery":"select * from user where 1 != 1",
      "Vindex":"user_index",
      "Values":5
   }
}

#Order by with math operations
"select * from user where id = 5 order by id+col collate utf8_general_ci desc"
{
   "Original":"select * from user where id = 5 order by id+col collate utf8_general_ci desc",
   "Instructions":{
      "Opcode":"SelectEqualUnique",
      "Keyspace":{
         "Name":"user",
         "Sharded":true
      },
      "Query":"select * from user where id = 5 order by id + col collate utf8_general_ci desc",
      "FieldQuery":"select * from user where 1 != 1",
      "Vindex":"user_index",
      "Values":5
   }
}

#Order by subquery column
"select * from user u join (select user_id from user_extra where user_id = 5) eu on u.id = eu.user_id where u.id = 5 order by eu.user_id"
{
   "Original":"select * from user u join (select user_id from user_extra where user_id = 5) eu on u.id = eu.user_id where u.id = 5 order by eu.user_id",
   "Instructions":{
      "Opcode":"SelectEqualUnique",
      "Keyspace":{
         "Name":"user",
         "Sharded":true
      },
      "Query":"select * from user as u join (select user_id from user_extra where user_id = 5) as eu on u.id = eu.user_id where u.id = 5 order by eu.user_id asc",
      "FieldQuery":"select * from user as u join (select user_id from user_extra where 1 != 1) as eu on u.id = eu.user_id where 1 != 1",
      "Vindex":"user_index",
      "Values":5
   }
}

# LIMIT
"select col1 from user where id = 1 limit 1"
{
  "Original": "select col1 from user where id = 1 limit 1",
  "Instructions": {
    "Opcode": "SelectEqualUnique",
    "Keyspace": {
      "Name": "user",
      "Sharded": true
    },
    "Query": "select col1 from user where id = 1 limit 1",
    "FieldQuery": "select col1 from user where 1 != 1",
    "Vindex": "user_index",
    "Values": 1
  }
}
