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

bug: the range of unsigned should be determined #1151

Closed
2 of 3 tasks
davidshiz opened this issue Dec 22, 2022 · 5 comments · Fixed by #1216
Closed
2 of 3 tasks

bug: the range of unsigned should be determined #1151

davidshiz opened this issue Dec 22, 2022 · 5 comments · Fixed by #1216
Assignees
Labels
A-bug Something isn't working C-stonedb-5.7 associated with stonedb 5.7 prio: high High priority

Comments

@davidshiz
Copy link
Collaborator

davidshiz commented Dec 22, 2022

Have you read the Contributing Guidelines on issues?

Please confirm if bug report does NOT exists already ?

  • I confirm there is no existing issue for this

Describe the problem

the range of unsigned ( INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT ) should be determined,
and when INSERT the unsigned data out of range, should return the correct prompt message.

mysql> create table test(
id1 TINYINT UNSIGNED,
id2 SMALLINT UNSIGNED,
id3 INT UNSIGNED,
id4 BIGINT UNSIGNED
);
Query OK, 0 rows affected (0.02 sec)

mysql> insert into test values(255,65535,4294967295,18446744073709551615);
Query OK, 1 row affected (0.00 sec)

mysql> insert into test values(253,65533,4294967293,18446744073709551613);
Query OK, 1 row affected (0.00 sec)

mysql> select * from test;
+------+-------+------------+----------------------+
| id1  | id2   | id3        | id4                  |
+------+-------+------------+----------------------+
|  127 | 32767 | 2147483647 | 18446744073709551615 |
|  127 | 32767 | 2147483647 | 18446744073709551613 |
+------+-------+------------+----------------------+
2 rows in set (0.00 sec)

Expected behavior

mysql> create table test(
id1 TINYINT UNSIGNED,
id2 SMALLINT UNSIGNED,
id3 INT UNSIGNED,
id4 BIGINT UNSIGNED
);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into test values(255,65535,4294967295,18446744073709551615);
Query OK, 1 row affected (0.00 sec)

mysql> insert into test values(253,65533,4294967293,18446744073709551613);
Query OK, 1 row affected (0.00 sec)

mysql> select * from test;
+------+-------+------------+----------------------+
| id1  | id2   | id3        | id4                  |
+------+-------+------------+----------------------+
|  255 | 65535 | 4294967295 | 18446744073709551615 |
|  253 | 65533 | 4294967293 | 18446744073709551613 |
+------+-------+------------+----------------------+
2 rows in set (0.00 sec)

How To Reproduce

create table test(id1 TINYINT UNSIGNED,id2 SMALLINT UNSIGNED,id3 INT UNSIGNED,id4 BIGINT UNSIGNED);
insert into test values(255,65535,4294967295,18446744073709551615);
insert into test values(253,65533,4294967293,18446744073709551613);
select * from test;

Environment

root@ub01:~# /stonedb57/install/bin/mysqld --version
/stonedb57/install/bin/mysqld  Ver 5.7.36-StoneDB for Linux on x86_64 (build-)
build information as follow:
        Repository address: https://github.com/stoneatom/stonedb.git:stonedb-5.7-dev
        Branch name: stonedb-5.7-dev
        Last commit ID: 863cebc58
        Last commit time: Date:   Wed Dec 7 14:16:34 2022 +0800
        Build time: Date: Mon Dec 19 14:29:02 CST 2022
root@ub01:~# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.5 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.5 LTS"
VERSION_ID="20.04"

Are you interested in submitting a PR to solve the problem?

  • Yes, I will!
@davidshiz davidshiz added the A-bug Something isn't working label Dec 22, 2022
@shangyanwen shangyanwen added this to the stonedb_5.7_v1.0.2 milestone Dec 22, 2022
@isredstar isredstar assigned hustjieke and unassigned DandreChen Dec 23, 2022
@hustjieke hustjieke moved this to In Progress in StoneDB for MySQL 5.7 Dec 23, 2022
@hustjieke
Copy link
Collaborator

MySQL will throw TYPE_WARN_OUT_OF_RANGE when signed/unsigned data out of range:

type_conversion_status Field_tiny::store(longlong nr, bool unsigned_val)
{
  ASSERT_COLUMN_MARKED_FOR_WRITE;
  type_conversion_status error= TYPE_OK;

  if (unsigned_flag)
  {
    if (nr < 0 && !unsigned_val)
    {
      *ptr= 0;
      set_warning(Sql_condition::SL_WARNING, ER_WARN_DATA_OUT_OF_RANGE, 1);
      error= TYPE_WARN_OUT_OF_RANGE;
    }
    else if ((ulonglong) nr > (ulonglong) 255)
    {
      *ptr= (char) 255;
      set_warning(Sql_condition::SL_WARNING, ER_WARN_DATA_OUT_OF_RANGE, 1);
      error= TYPE_WARN_OUT_OF_RANGE;
    }
    else
      *ptr=(char) nr;
  }
  else
  {
    if (nr < 0 && unsigned_val)
      nr= 256;                                    // Generate overflow
    if (nr < -128)
    {
      *ptr= (char) -128;
      set_warning(Sql_condition::SL_WARNING, ER_WARN_DATA_OUT_OF_RANGE, 1);
      error= TYPE_WARN_OUT_OF_RANGE;
    }
    else if (nr > 127)
    {
      *ptr=127;
      set_warning(Sql_condition::SL_WARNING, ER_WARN_DATA_OUT_OF_RANGE, 1);
      error= TYPE_WARN_OUT_OF_RANGE;
    }
    else
      *ptr=(char) nr;
  }
  return error;
}

For tianmu engine, the data will be truncated:

      case MYSQL_TYPE_TINY: {
        int64_t v = f->val_int();
        if (v > TIANMU_TINYINT_MAX)
          v = TIANMU_TINYINT_MAX;
        else if (v < TIANMU_TINYINT_MIN)
          v = TIANMU_TINYINT_MIN;
        *reinterpret_cast<int64_t *>(ptr) = v;
        ptr += sizeof(int64_t);
      } break;

@hustjieke hustjieke mentioned this issue Jan 5, 2023
3 tasks
@hustjieke
Copy link
Collaborator

Out-of-Range and Overflow Handling

  • If strict SQL mode is enabled, MySQL rejects the out-of-range value with an error, and the insert fails, in accordance with the SQL standard.

  • If no restrictive modes are enabled, MySQL clips the value to the appropriate endpoint of the column data type range and stores the resulting value instead.

For more infos:
https://dev.mysql.com/doc/refman/8.0/en/out-of-range-and-overflow.html

@hustjieke
Copy link
Collaborator

All unsigned boundary values ​​are supported in my demo feature, I used it to verify my idea and it works well for now, I'll pr the code as soon as possible!

I'll write the design docs to desc how to impl all boundary values on integer types(including from tynyint to bigint).
My demo feature branch:
https://github.com/hustjieke/stonedb/tree/feat_unsigned_support

@davidshiz
Copy link
Collaborator Author

similar to #1206

CREATE TABLE `test` (
  `id1` tinyint(3) unsigned DEFAULT NULL,
  `id2` smallint(5) unsigned DEFAULT NULL,
  `id3` int(10) unsigned DEFAULT NULL,
  `id4` bigint(20) unsigned DEFAULT NULL
)DEFAULT CHARSET=utf8mb4;

insert into test values (255,65535,4294967295,18446744073709551615);
insert into test values (255,65535,4294967295,9223372036854775807);
insert into test values (129,32769,2147483647,9223372036854775808);

mysql> select * from test;
+------+-------+------------+----------------------+
| id1  | id2   | id3        | id4                  |
+------+-------+------------+----------------------+
|  127 | 32767 | 2147483647 | 18446744073709551615 |
|  127 | 32767 | 2147483647 |  9223372036854775807 |
|  127 | 32767 | 2147483647 |                 NULL |
+------+-------+------------+----------------------+
3 rows in set (0.00 sec)

@hustjieke hustjieke added prio: high High priority C-stonedb-5.7 associated with stonedb 5.7 labels Jan 11, 2023
@hustjieke
Copy link
Collaborator

Tianmu engine deal with unsigned data with different way:

  • With tianmu_insert_delayed=ON and tianmu_enable_rowstore=ON/OFF mode, the integer data will be truncated if unsigned integer is bigger than max signed integer
void Engine::EncodeRecord {
      switch (f->type()) {
      case MYSQL_TYPE_TINY: {
        int64_t v = f->val_int();
        if (v > TIANMU_TINYINT_MAX)
          v = TIANMU_TINYINT_MAX;
        else if (v < TIANMU_TINYINT_MIN)
          v = TIANMU_TINYINT_MIN;
        *reinterpret_cast<int64_t *>(ptr) = v;
        ptr += sizeof(int64_t);
      } break;
  ...
  ...
}

call stack:

Tianmu::core::Engine::EncodeRecord(Tianmu::core::Engine * const this, const std::string & table_path, int table_id, Field ** field, size_t col, size_t blobs, std::unique_ptr<char [], std::default_delete<char []> > & buf, uint32_t & size) (\github\stonedb\storage\tianmu\core\engine.cpp:464)
Tianmu::core::Engine::InsertMemRow(Tianmu::core::Engine * const this, const std::string & table_path, std::shared_ptr<Tianmu::core::TableShare> & share, TABLE * table) (\github\stonedb\storage\tianmu\core\engine.cpp:1480)
Tianmu::core::Engine::InsertRow(Tianmu::core::Engine * const this, const std::string & table_path, Tianmu::core::Transaction * trans_, TABLE * table, std::shared_ptr<Tianmu::core::TableShare> & share) (\github\stonedb\storage\tianmu\core\engine.cpp:1491)
Tianmu::handler::ha_tianmu::write_row(Tianmu::handler::ha_tianmu * const this, uchar * buf) (\github\stonedb\storage\tianmu\handler\ha_tianmu.cpp:466)
handler::ha_write_row(handler * const this, uchar * buf) (\github\stonedb\sql\handler.cc:8189)
...
...
  • With tianmu_insert_delayed=OFF mode, Tianmu engine do not truncate if the integer is out of range when encording integer data. The data getted from field stored into ValueCache directly.
void TianmuTable::Field2VC(Field *f, loader::ValueCache &vc, size_t col) {
  ...
  ...
  switch (f->type()) {
    case MYSQL_TYPE_TINY:
    case MYSQL_TYPE_SHORT:
    case MYSQL_TYPE_LONG:
    case MYSQL_TYPE_INT24:
    case MYSQL_TYPE_LONGLONG:
    case MYSQL_TYPE_BIT: {
      int64_t value = f->val_int();
      if (m_attrs[col]->GetIfAutoInc() && value == 0)
        // Value of auto inc column was not assigned by user
        *reinterpret_cast<int64_t *>(vc.Prepare(sizeof(int64_t))) = m_attrs[col]->AutoIncNext();
      else
        *reinterpret_cast<int64_t *>(vc.Prepare(sizeof(int64_t))) = value;
      vc.ExpectedSize(sizeof(int64_t));

call stack:

Tianmu::core::TianmuTable::Field2VC(Tianmu::core::TianmuTable * const this, Field * f, Tianmu::loader::ValueCache & vc, size_t col) (\github\stonedb\storage\tianmu\core\tianmu_table.cpp:603)
Tianmu::core::TianmuTable::Insert(Tianmu::core::TianmuTable * const this, TABLE * table) (\github\stonedb\storage\tianmu\core\tianmu_table.cpp:734)
Tianmu::core::Engine::InsertRow(Tianmu::core::Engine * const this, const std::string & table_path, Tianmu::core::Transaction * trans_, TABLE * table, std::shared_ptr<Tianmu::core::TableShare> & share) (\github\stonedb\storage\tianmu\core\engine.cpp:1499)
Tianmu::handler::ha_tianmu::write_row(Tianmu::handler::ha_tianmu * const this, uchar * buf) (\github\stonedb\storage\tianmu\handler\ha_tianmu.cpp:466)
handler::ha_write_row(handler * const this, uchar * buf) (\github\stonedb\sql\handler.cc:8189)
...
...

hustjieke added a commit to hustjieke/stonedb-8.0.30-upgrade that referenced this issue Jan 12, 2023
[summary]

tinyint: signed range is -128 to 127, unsigned range is 0 to 127.

smallint: signed range is -32768 to 32767, unsigned range is 0 to 32767.

mediumint: signed range is -8388608 to 8388607, unsigned range is 0 to 8388607.

int/integer: signed range is -2147483647 to 2147483647, unsigned range is 0 to 2147483647.
Note: -2147483648 is not allowed in tianmu engine currently.

bigint: signed range is -9223372036854775806 to 9223372036854775807, unsigned range is 0 to 9223372036854775807.
Note: -9223372036854775807 will be set to null and -9223372036854775808 will ret out of range.
hustjieke added a commit to hustjieke/stonedb-8.0.30-upgrade that referenced this issue Jan 12, 2023
[summary]

tinyint: signed range is -128 to 127, unsigned range is 0 to 127.

smallint: signed range is -32768 to 32767, unsigned range is 0 to 32767.

mediumint: signed range is -8388608 to 8388607, unsigned range is 0 to 8388607.

int/integer: signed range is -2147483647 to 2147483647, unsigned range is 0 to 2147483647.
Note: -2147483648 is not allowed in tianmu engine currently.

bigint: signed range is -9223372036854775806 to 9223372036854775807, unsigned range is 0 to 9223372036854775807.
Note: -9223372036854775807 will be set to null and -9223372036854775808 will ret out of range.
hustjieke added a commit to hustjieke/stonedb-8.0.30-upgrade that referenced this issue Jan 12, 2023
…file test unsigned, this will be opened after we completely support unsigned types stoneatom#1151
hustjieke added a commit to hustjieke/stonedb-8.0.30-upgrade that referenced this issue Jan 13, 2023
hustjieke added a commit to hustjieke/stonedb-8.0.30-upgrade that referenced this issue Jan 13, 2023
hustjieke added a commit to hustjieke/stonedb-8.0.30-upgrade that referenced this issue Jan 13, 2023
@mergify mergify bot closed this as completed in #1216 Jan 13, 2023
mergify bot pushed a commit that referenced this issue Jan 13, 2023
[summary]

tinyint: signed range is -128 to 127, unsigned range is 0 to 127.

smallint: signed range is -32768 to 32767, unsigned range is 0 to 32767.

mediumint: signed range is -8388608 to 8388607, unsigned range is 0 to 8388607.

int/integer: signed range is -2147483647 to 2147483647, unsigned range is 0 to 2147483647.
Note: -2147483648 is not allowed in tianmu engine currently.

bigint: signed range is -9223372036854775806 to 9223372036854775807, unsigned range is 0 to 9223372036854775807.
Note: -9223372036854775807 will be set to null and -9223372036854775808 will ret out of range.
mergify bot pushed a commit that referenced this issue Jan 13, 2023
…file test unsigned, this will be opened after we completely support unsigned types #1151
@github-project-automation github-project-automation bot moved this from In Progress to Done in StoneDB for MySQL 5.7 Jan 13, 2023
hustjieke added a commit to hustjieke/stonedb-8.0.30-upgrade that referenced this issue Feb 13, 2023
[summary]
1. expand unsigned boundary from signed boundary to max valued.
2. code cover create/insert(delayed/no delayed mode)/update/delete/select.
3. functions and operators(agg and math calculation)

refs: stoneatom#1266
related issue: stoneatom#1151
hustjieke added a commit to hustjieke/stonedb-8.0.30-upgrade that referenced this issue Feb 21, 2023
[summary]
1. expand unsigned boundary from signed boundary to max valued.
2. code cover create/insert(delayed/no delayed mode)/update/delete/select.
3. functions and operators(agg and math calculation)

refs: stoneatom#1266
related issue: stoneatom#1151
hustjieke added a commit to hustjieke/stonedb-8.0.30-upgrade that referenced this issue Feb 24, 2023
[summary]
1. expand unsigned boundary from signed boundary to max valued.
2. code cover create/insert(delayed/no delayed mode)/update/delete/select.
3. functions and operators(agg and math calculation)

refs: stoneatom#1266
related issue: stoneatom#1151
hustjieke added a commit to hustjieke/stonedb-8.0.30-upgrade that referenced this issue Feb 27, 2023
[summary]
1. expand unsigned boundary from signed boundary to max valued.
2. code cover create/insert(delayed/no delayed mode)/update/delete/select.
3. functions and operators(agg and math calculation)

refs: stoneatom#1266
related issue: stoneatom#1151
mergify bot pushed a commit that referenced this issue Feb 27, 2023
[summary]
1. expand unsigned boundary from signed boundary to max valued.
2. code cover create/insert(delayed/no delayed mode)/update/delete/select.
3. functions and operators(agg and math calculation)

refs: #1266
related issue: #1151
hustjieke added a commit to hustjieke/stonedb-8.0.30-upgrade that referenced this issue Feb 28, 2023
[summary]
1. expand unsigned boundary from signed boundary to max valued.
2. code cover create/insert(delayed/no delayed mode)/update/delete/select.
3. functions and operators(agg and math calculation)

refs: stoneatom#1266
related issue: stoneatom#1151
mergify bot pushed a commit that referenced this issue Mar 6, 2023
[summary]
1. expand unsigned boundary from signed boundary to max valued.
2. code cover create/insert(delayed/no delayed mode)/update/delete/select.
3. functions and operators(agg and math calculation)

refs: #1266
related issue: #1151
konghaiya pushed a commit to konghaiya/stonedb that referenced this issue Mar 7, 2023
[summary]

tinyint: signed range is -128 to 127, unsigned range is 0 to 127.

smallint: signed range is -32768 to 32767, unsigned range is 0 to 32767.

mediumint: signed range is -8388608 to 8388607, unsigned range is 0 to 8388607.

int/integer: signed range is -2147483647 to 2147483647, unsigned range is 0 to 2147483647.
Note: -2147483648 is not allowed in tianmu engine currently.

bigint: signed range is -9223372036854775806 to 9223372036854775807, unsigned range is 0 to 9223372036854775807.
Note: -9223372036854775807 will be set to null and -9223372036854775808 will ret out of range.
konghaiya pushed a commit to konghaiya/stonedb that referenced this issue Mar 7, 2023
…file test unsigned, this will be opened after we completely support unsigned types stoneatom#1151
konghaiya pushed a commit to konghaiya/stonedb that referenced this issue Mar 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-bug Something isn't working C-stonedb-5.7 associated with stonedb 5.7 prio: high High priority
Projects
Development

Successfully merging a pull request may close this issue.

4 participants