Skip to content
  • Catalin Besleaga's avatar
    ca742a4c
    WL#8699 Bit-wise operations on binary data types · ca742a4c
    Catalin Besleaga authored
    PROBLEM
    =======
    Existing bit-wise operations: & | ^ ~ << >> BIT_COUNT BIT_AND BIT_XOR
    BIT_OR currently take BIGINT (64-bit integer) arguments and return
    BIGINT. So they are limited to 64 bits.
    Task is to extend them to also work on
    binary([VAR]BINARY/[TINY|MEDIUM|LONG]BLOB) arguments of any length
    for ( & | ^ ~ << >> BIT_COUNT) and limited to 511 bytes
    ([VAR]BINARY/TINYBLOB)for the aggregate functions BIT_AND BIT_XOR
    BIT_OR.
    
    Solution:
    =========
    Implement binary operations for
    [VAR]BINARY(M)/[TINY|MEDIUM|LONG]BLOB(M).
    Depending on the types of input arguments of & | ^ ~ << >> BIT_AND
    BIT_XOR BIT_OR BIT_COUNT:
    - determine the return type (today it is INT_RESULT): a hybrid of
    INT_RESULT and STRING_RESULT (like '+' does); this doesn't apply to
    BIT_COUNT which result type will remain INT_RESULT.
    - call val_int() or val_str() on arguments
    - do calculations (for integer arguments, continue using the native C++
    bit-wise operators; for binary, do that byte-by-byte).
    The operation's return type will be determined as follows.
    
    1.  arg1 [ & | ^] arg2 (bit-and, bit-or, bit-xor)
    -------------------------------------------------
    Currently in 5.7: both arguments are converted to BIGINT and the result
    of the operation is returned as BIGINT.
    
    Solution:
    
    1.1. when arg1 is [VAR]BINARY(m)/[TINY|MEDIUM|LONG]BLOB(m) and arg2 is
    [VAR]BINARY(n)/[TINY|MEDIUM|LONG]BLOB(n) and at least one of them is not
    a hex/bit/NULL literal
    1.1.a. Determine the length of each argument:
    l1=LENGTH(arg 1), l2=LENGTH(arg 2).
    Note that l1 =< m, l2 =< n; if types are BINARY there is equality.
    1.1.b If l1 <> l2, throw error (anything else would require padding to
    left or right, and we can't reliably decide between left and right)
    1.1.c Execute the bitwise operation. Return type is VARBINARY(the length
    of the result is l1 i.e. l1=l2 per 1.1.b).
    
    1.2. otherwise,
    convert both arguments to BIGINT, execute the operation and return
    BIGINT; this is the same behaviour as MySQL 5.7.
    
    2.  arg1 [ << >> ] arg2 (bit shifting) ; ~(arg1) (bit-not)
    ----------------------------------------------------------
    Currently in 5.7: arg1 is converted to BIGINT and the result of the
    operation is returned as BIGINT.
    
    Solution:
    
    2.1. when arg1 is [VAR]BINARY(m)/[TINY|MEDIUM|LONG]BLOB(m) and is not a
    hex/bit/NULL literal, execute the operation and return the result as
    [VAR]BINARY(m). For shift operators, bits may be lost without warning
    (as is usual for the BIGINT case: 1>>1 is 0).
    
    2.2. otherwise
    convert to BIGINT execute operation and return BIGINT. This
    is the same behavior as MySQL 5.7.
    
    3. BIT_COUNT
    ------------
    always returns BIGINT(extended to work on binary data types)
    
    4. BIT_AND, BIT_XOR, BIT_OR
    ---------------------------
    4.1. when arg is [VAR]BINARY(m)/TINYBLOB(m) and is not a hex/bit/NULL
    literal
    4.1.1. if arg's values have same length execute the operation and return
    the result as [VAR]BINARY(m)
    4.1.2. if arg's values have different length throw error
    4.2. when arg is [MEDIUM|LONG]BLOB(m) or [VAR]BINARY(n) with n exceeding
    511 throw ER_INVALID_BITWISE_AGGREGATE_OPERANDS_SIZE error
    4.3. when the arg is other types than those in 4.1 or 4.2 work as before
    => returns BIGINT
    
    *NULL values do not affect the result unless all the values are NULL, in
    which  case the result will be the neutral element having the same
    length as the column definition length
    ca742a4c
    WL#8699 Bit-wise operations on binary data types
    Catalin Besleaga authored
    PROBLEM
    =======
    Existing bit-wise operations: & | ^ ~ << >> BIT_COUNT BIT_AND BIT_XOR
    BIT_OR currently take BIGINT (64-bit integer) arguments and return
    BIGINT. So they are limited to 64 bits.
    Task is to extend them to also work on
    binary([VAR]BINARY/[TINY|MEDIUM|LONG]BLOB) arguments of any length
    for ( & | ^ ~ << >> BIT_COUNT) and limited to 511 bytes
    ([VAR]BINARY/TINYBLOB)for the aggregate functions BIT_AND BIT_XOR
    BIT_OR.
    
    Solution:
    =========
    Implement binary operations for
    [VAR]BINARY(M)/[TINY|MEDIUM|LONG]BLOB(M).
    Depending on the types of input arguments of & | ^ ~ << >> BIT_AND
    BIT_XOR BIT_OR BIT_COUNT:
    - determine the return type (today it is INT_RESULT): a hybrid of
    INT_RESULT and STRING_RESULT (like '+' does); this doesn't apply to
    BIT_COUNT which result type will remain INT_RESULT.
    - call val_int() or val_str() on arguments
    - do calculations (for integer arguments, continue using the native C++
    bit-wise operators; for binary, do that byte-by-byte).
    The operation's return type will be determined as follows.
    
    1.  arg1 [ & | ^] arg2 (bit-and, bit-or, bit-xor)
    -------------------------------------------------
    Currently in 5.7: both arguments are converted to BIGINT and the result
    of the operation is returned as BIGINT.
    
    Solution:
    
    1.1. when arg1 is [VAR]BINARY(m)/[TINY|MEDIUM|LONG]BLOB(m) and arg2 is
    [VAR]BINARY(n)/[TINY|MEDIUM|LONG]BLOB(n) and at least one of them is not
    a hex/bit/NULL literal
    1.1.a. Determine the length of each argument:
    l1=LENGTH(arg 1), l2=LENGTH(arg 2).
    Note that l1 =< m, l2 =< n; if types are BINARY there is equality.
    1.1.b If l1 <> l2, throw error (anything else would require padding to
    left or right, and we can't reliably decide between left and right)
    1.1.c Execute the bitwise operation. Return type is VARBINARY(the length
    of the result is l1 i.e. l1=l2 per 1.1.b).
    
    1.2. otherwise,
    convert both arguments to BIGINT, execute the operation and return
    BIGINT; this is the same behaviour as MySQL 5.7.
    
    2.  arg1 [ << >> ] arg2 (bit shifting) ; ~(arg1) (bit-not)
    ----------------------------------------------------------
    Currently in 5.7: arg1 is converted to BIGINT and the result of the
    operation is returned as BIGINT.
    
    Solution:
    
    2.1. when arg1 is [VAR]BINARY(m)/[TINY|MEDIUM|LONG]BLOB(m) and is not a
    hex/bit/NULL literal, execute the operation and return the result as
    [VAR]BINARY(m). For shift operators, bits may be lost without warning
    (as is usual for the BIGINT case: 1>>1 is 0).
    
    2.2. otherwise
    convert to BIGINT execute operation and return BIGINT. This
    is the same behavior as MySQL 5.7.
    
    3. BIT_COUNT
    ------------
    always returns BIGINT(extended to work on binary data types)
    
    4. BIT_AND, BIT_XOR, BIT_OR
    ---------------------------
    4.1. when arg is [VAR]BINARY(m)/TINYBLOB(m) and is not a hex/bit/NULL
    literal
    4.1.1. if arg's values have same length execute the operation and return
    the result as [VAR]BINARY(m)
    4.1.2. if arg's values have different length throw error
    4.2. when arg is [MEDIUM|LONG]BLOB(m) or [VAR]BINARY(n) with n exceeding
    511 throw ER_INVALID_BITWISE_AGGREGATE_OPERANDS_SIZE error
    4.3. when the arg is other types than those in 4.1 or 4.2 work as before
    => returns BIGINT
    
    *NULL values do not affect the result unless all the values are NULL, in
    which  case the result will be the neutral element having the same
    length as the column definition length
Loading