Skip to content

Commit

Permalink
sql: add get_bit() and set_bit() builtin functions
Browse files Browse the repository at this point in the history
Resolve cockroachdb#45851

This commit adds builtin function get_bit() and set_bit(),
along with thier respective testcases.

Characteristics of the above builtin functions are:
    * get_bit() allows us to extracts a bit at given index in
      the bit array.
    * set_bit() enable us updates a bit at given index in the
      bit array.

Release justification: first good issue, adding builtin functions.

Release note (sql change): This PR is introduced to add get_bits()
and set_bit() builtin functions.
  • Loading branch information
abhishek20123g committed Mar 12, 2020
1 parent 63b956c commit 3ba58b5
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 0 deletions.
4 changes: 4 additions & 0 deletions docs/generated/sql/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -865,6 +865,8 @@ has no relationship with the commit order of concurrent transactions.</p>
</span></td></tr>
<tr><td><a name="from_uuid"></a><code>from_uuid(val: <a href="bytes.html">bytes</a>) &rarr; <a href="string.html">string</a></code></td><td><span class="funcdesc"><p>Converts the byte string representation of a UUID to its character string representation.</p>
</span></td></tr>
<tr><td><a name="get_bit"></a><code>get_bit(bit_string: varbit, index: <a href="int.html">int</a>) &rarr; <a href="int.html">int</a></code></td><td><span class="funcdesc"><p>Extracts a bit at given index in the bit array</p>
</span></td></tr>
<tr><td><a name="initcap"></a><code>initcap(val: <a href="string.html">string</a>) &rarr; <a href="string.html">string</a></code></td><td><span class="funcdesc"><p>Capitalizes the first letter of <code>val</code>.</p>
</span></td></tr>
<tr><td><a name="left"></a><code>left(input: <a href="bytes.html">bytes</a>, return_set: <a href="int.html">int</a>) &rarr; <a href="bytes.html">bytes</a></code></td><td><span class="funcdesc"><p>Returns the first <code>return_set</code> bytes from <code>input</code>.</p>
Expand Down Expand Up @@ -1007,6 +1009,8 @@ has no relationship with the commit order of concurrent transactions.</p>
</span></td></tr>
<tr><td><a name="rtrim"></a><code>rtrim(val: <a href="string.html">string</a>) &rarr; <a href="string.html">string</a></code></td><td><span class="funcdesc"><p>Removes all spaces from the end (right-hand side) of <code>val</code>.</p>
</span></td></tr>
<tr><td><a name="set_bit"></a><code>set_bit(bit_string: varbit, index: <a href="int.html">int</a>, to_set: <a href="int.html">int</a>) &rarr; varbit</code></td><td><span class="funcdesc"><p>Updates a bit at given index in the bit array</p>
</span></td></tr>
<tr><td><a name="sha1"></a><code>sha1(<a href="bytes.html">bytes</a>...) &rarr; <a href="string.html">string</a></code></td><td><span class="funcdesc"><p>Calculates the SHA1 hash value of a set of values.</p>
</span></td></tr>
<tr><td><a name="sha1"></a><code>sha1(<a href="string.html">string</a>...) &rarr; <a href="string.html">string</a></code></td><td><span class="funcdesc"><p>Calculates the SHA1 hash value of a set of values.</p>
Expand Down
25 changes: 25 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/builtin_function
Original file line number Diff line number Diff line change
Expand Up @@ -2563,3 +2563,28 @@ query T
SELECT getdatabaseencoding()
----
UTF8

subtest get_bit

query I
SELECT get_bit(B'100101110101', 3) UNION SELECT get_bit(B'100101110101', 2)
----
1
0

query error get_bit\(\): GetBitAtIndex: bit index 10 out of valid range \(0..4\)
SELECT get_bit(B'10110', 10)

subtest set_bit

query T
SELECT set_bit(B'1101010', 0, 0) UNION SELECT set_bit(B'1101010', 2, 1)
----
0101010
1111010

query error set_bit\(\): SetBitAtIndex: bit index 10 out of valid range \(0..6\)
SELECT set_bit(B'1101010', 10, 1)

query error set_bit\(\): to_set value must be either 0 or 1 only.
SELECT set_bit(B'1001010', 0, 2)
45 changes: 45 additions & 0 deletions pkg/sql/sem/builtins/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,51 @@ var builtins = map[string]builtinDefinition{
"Supports encodings 'UTF8' and 'LATIN1'.",
}),

// https://www.postgresql.org/docs/9.0/functions-binarystring.html#FUNCTIONS-BINARYSTRING-OTHER
"get_bit": makeBuiltin(tree.FunctionProperties{Category: categoryString},
tree.Overload{
Types: tree.ArgTypes{{"bit_string", types.VarBit}, {"index", types.Int}},
ReturnType: tree.FixedReturnType(types.Int),
Fn: func(_ *tree.EvalContext, args tree.Datums) (tree.Datum, error) {
bitString := tree.MustBeDBitArray(args[0])
index := tree.MustBeDInt(args[1])
bit, err := bitString.GetBitAtIndex(int(index))
if err != nil {
return nil, err
}
return tree.NewDInt(tree.DInt(bit)), nil
},
Info: "Extracts a bit at given index in the bit array",
}),

// https://www.postgresql.org/docs/9.0/functions-binarystring.html#FUNCTIONS-BINARYSTRING-OTHER
"set_bit": makeBuiltin(tree.FunctionProperties{Category: categoryString},
tree.Overload{
Types: tree.ArgTypes{
{"bit_string", types.VarBit},
{"index", types.Int},
{"to_set", types.Int},
},
ReturnType: tree.FixedReturnType(types.VarBit),
Fn: func(_ *tree.EvalContext, args tree.Datums) (tree.Datum, error) {
bitString := tree.MustBeDBitArray(args[0])
index := tree.MustBeDInt(args[1])
toSet := tree.MustBeDInt(args[2])

// Value of bit can only be set to 1 or 0.
if int(toSet) != 0 && int(toSet) != 1 {
return nil, pgerror.Newf(pgcode.InvalidParameterValue,
"to_set value must be either 0 or 1 only.")
}
updatedBitString, err := bitString.SetBitAtIndex(int(index), int(toSet))
if err != nil {
return nil, err
}
return &tree.DBitArray{BitArray: updatedBitString}, nil
},
Info: "Updates a bit at given index in the bit array",
}),

"gen_random_uuid": makeBuiltin(
tree.FunctionProperties{
Category: categoryIDGeneration,
Expand Down

0 comments on commit 3ba58b5

Please sign in to comment.