vitessio / vitess

Vitess is a database clustering system for horizontal scaling of MySQL.
http://vitess.io
Apache License 2.0
18.48k stars 2.09k forks source link

Vtgate returns the wrong type #16112

Open systay opened 3 months ago

systay commented 3 months ago

Given the following query:

SELECT 
    (SELECT SUM(LENGTH(extra_info)) FROM user_extra) AS total_length_extra_info 
FROM user;

Vitess returns the wrong type. MySQL would return a DECIMAL, but Vitess returns an INT64.

The weird thing is that this only happens then the SUM query is in a subquery - if run as a standalone query we get the correct type.

The plan used is:

{
  "QueryType": "SELECT",
  "Original": "SELECT (SELECT SUM(LENGTH(extra_info)) FROM user_extra) AS total_length_extra_info",
  "Instructions": {
    "OperatorType": "UncorrelatedSubquery",
    "Variant": "PulloutValue",
    "PulloutVars": [
      "__sq1"
    ],
    "Inputs": [
      {
        "InputName": "SubQuery",
        "OperatorType": "Aggregate",
        "Variant": "Scalar",
        "Aggregates": "sum(0) AS sum(LENGTH(extra_info))",
        "Inputs": [
          {
            "OperatorType": "Route",
            "Variant": "Scatter",
            "Keyspace": {
              "Name": "user",
              "Sharded": true
            },
            "FieldQuery": "select sum(LENGTH(extra_info)) from user_extra where 1 != 1",
            "Query": "select sum(LENGTH(extra_info)) from user_extra",
            "Table": "user_extra"
          }
        ]
      },
      {
        "InputName": "Outer",
        "OperatorType": "Route",
        "Variant": "Reference",
        "Keyspace": {
          "Name": "main",
          "Sharded": false
        },
        "FieldQuery": "select :__sq1 as total_length_extra_info from dual where 1 != 1",
        "Query": "select :__sq1 as total_length_extra_info from dual",
        "Table": "dual"
      }
    ]
  },
  "TablesUsed": [
    "main.dual",
    "user.user_extra"
  ]
}
dbussink commented 3 months ago

There's another thing that goes wrong here when there's no row(s). MySQL returns no rows, but with a NEWDECIMAL type, by Vitess seems to return NULL_TYPE.

Test failure output

--- FAIL: TestSubqueries (0.02s)
    --- FAIL: TestSubqueries/0_SELECT_(SELECT_SUM(LENGTH(extra_info))_FROM_user_extra)_AS_total_length_extra_info_FROM_user (0.00s)
        mysql.go:265: for column total_length_extra_info field types do not match
            Not equal: 
            MySQL: DECIMAL
            Vitess: NULL_TYPE

Canonical MySQL output

mysql> SELECT SUM(LENGTH(extra_info)) FROM user_extra;
Field   1:  `SUM(LENGTH(extra_info))`
Catalog:    `def`
Database:   ``
Table:      ``
Org_table:  ``
Type:       NEWDECIMAL
Collation:  binary (63)
Length:     32
Max_length: 0
Decimals:   0
Flags:      BINARY NUM 

+-------------------------+
| SUM(LENGTH(extra_info)) |
+-------------------------+
|                    NULL |
+-------------------------+
1 row in set (0.01 sec)

mysql> SELECT (SELECT SUM(LENGTH(extra_info)) FROM user_extra) AS total_length_extra_info FROM user;
Field   1:  `total_length_extra_info`
Catalog:    `def`
Database:   ``
Table:      ``
Org_table:  ``
Type:       NEWDECIMAL
Collation:  binary (63)
Length:     32
Max_length: 0
Decimals:   0
Flags:      BINARY NUM 

0 rows in set (0.01 sec)