Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expression: handle empty input and improve compatibility for format #8797

Merged
merged 9 commits into from
Jan 2, 2019

Conversation

eurekaka
Copy link
Contributor

@eurekaka eurekaka commented Dec 25, 2018

What problem does this PR solve?

Before this PR, in TiDB:

mysql> select format('', 1);
ERROR 2013 (HY000): Lost connection to MySQL server during query

mysql> select format(1, '');
ERROR 2013 (HY000): Lost connection to MySQL server during query

mysql> select length(format(1, 10240));
+--------------------------+
| length(format(1, 10240)) |
+--------------------------+
|                    10242 |
+--------------------------+
1 row in set (0.00 sec)

while in MySQL 5.7.10:

mysql> select format('', 1);
+---------------+
| format('', 1) |
+---------------+
| 0.0           |
+---------------+
1 row in set (0.00 sec)

mysql> select format(1, '');
+---------------+
| format(1, '') |
+---------------+
| 1             |
+---------------+
1 row in set, 1 warning (0.01 sec)

mysql> select format(1, 10240);
+----------------------------------+
| format(1, 10240)                 |
+----------------------------------+
| 1.000000000000000000000000000000 |
+----------------------------------+
1 row in set (0.00 sec)

mysql> select length(format(1, 10240));
+--------------------------+
| length(format(1, 10240)) |
+--------------------------+
|                       32 |
+--------------------------+
1 row in set (0.00 sec)

What is changed and how it works?

const int FORMAT_MAX_DECIMALS= 30;

String *Item_func_format::val_str_ascii(String *str)
{
  /* Number of decimal digits */
  int dec;

  dec= (int) args[1]->val_int();
  if (args[1]->null_value)
  {
    null_value=1;
    return NULL;
  }

  dec= set_zone(dec, 0, FORMAT_MAX_DECIMALS);
  ...
}
  • make result of select format(1, 4, null) compatible with MySQL.

Check List

Tests

  • Unit test: new unit tests added, and existing unit tests are updated to be compatible with MySQL.

Code changes

N/A

Side effects

N/A

Related changes


This change is Reviewable

Copy link
Member

@winoros winoros left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rest lgtm

expression/builtin_string.go Outdated Show resolved Hide resolved
- change format with locale
- modify tests
- handle null in format with locale
// evalString evals FORMAT(X,D).
// See https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_format
func (b *builtinFormatSig) evalString(row chunk.Row) (string, bool, error) {
x, isNull, err := b.args[0].EvalString(b.ctx, row)
x, isNull, err := b.args[0].EvalReal(b.ctx, row)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The argument types are all ETString: https://github.com/pingcap/tidb/pull/8797/files#diff-314e997a9df9b116e8f0aad4149df468R2920. We should not change EvalString() to EvalReal().

Copy link
Contributor Author

@eurekaka eurekaka Dec 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the output of MySQL:

mysql> select format("1a","2a");
+-------------------+
| format("1a","2a") |
+-------------------+
| 1.00              |
+-------------------+
1 row in set, 2 warnings (0.00 sec)

mysql> show warnings;
+---------+------+-----------------------------------------+
| Level   | Code | Message                                 |
+---------+------+-----------------------------------------+
| Warning | 1292 | Truncated incorrect INTEGER value: '2a' |
| Warning | 1292 | Truncated incorrect DOUBLE value: '1a'  |
+---------+------+-----------------------------------------+
2 rows in set (0.00 sec)

Seems MySQL believes the type of parameters to be Double and Integer, but it is not reflected in https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_format.

Copy link
Contributor Author

@eurekaka eurekaka Dec 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In MySQL source code, for function format(X, D), X is evaluated as decimal or double type, while D is evaluated as integer type.

  dec= (int) args[1]->val_int();
  if (args[0]->result_type() == DECIMAL_RESULT ||
      args[0]->result_type() == INT_RESULT)
  {
    res= args[0]->val_decimal(&dec_val);
  }
  else
  {
    double nr= args[0]->val_real();
  }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eurekaka
Copy link
Contributor Author

@zz-jason @winoros comments addressed, PTAL

@eurekaka
Copy link
Contributor Author

@lamxTyler @XuHuaiyu PTAL

Copy link
Contributor

@alivxxx alivxxx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@alivxxx alivxxx added the status/LGT1 Indicates that a PR has LGTM 1. label Dec 29, 2018
Copy link
Member

@zz-jason zz-jason left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@zz-jason zz-jason added status/LGT2 Indicates that a PR has LGTM 2. and removed status/LGT1 Indicates that a PR has LGTM 1. labels Jan 2, 2019
@zz-jason
Copy link
Member

zz-jason commented Jan 2, 2019

/run-all-tests

@eurekaka
Copy link
Contributor Author

eurekaka commented Jan 2, 2019

/run-common-test

1 similar comment
@eurekaka
Copy link
Contributor Author

eurekaka commented Jan 2, 2019

/run-common-test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component/expression status/LGT2 Indicates that a PR has LGTM 2. type/bugfix This PR fixes a bug. type/compatibility
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants