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 functions get_bit() and set_bit(),
along with thier respective testcases.

Characteristics of the above functions are:
    * get_bit() allows us to extract a particular bit from
      a given array of bits.
    * set_bit() will enable us to modify a specific bit in
      a given array of bits.

Release note: This PR is introduced to add get_bits() and
set_bit() builtin functions.
  • Loading branch information
abhishek20123g committed Mar 10, 2020
1 parent bc169fd commit a356203
Show file tree
Hide file tree
Showing 3 changed files with 73 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(val: varbit, position: <a href="int.html">int</a>) &rarr; <a href="int.html">int</a></code></td><td><span class="funcdesc"><p>extract a particular bit from a given array of bits</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(val: varbit, position: <a href="int.html">int</a>, toSet: <a href="int.html">int</a>) &rarr; varbit</code></td><td><span class="funcdesc"><p>Set particular bit in a given array of bits</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
22 changes: 22 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,25 @@ 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\(\): 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\(\): bit index 10 out of valid range \(0..6\)
SELECT set_bit(B'1101010', 10, 1)
47 changes: 47 additions & 0 deletions pkg/sql/sem/builtins/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,53 @@ 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{{"val", types.VarBit}, {"position", types.Int}},
ReturnType: tree.FixedReturnType(types.Int),
Fn: func(_ *tree.EvalContext, args tree.Datums) (tree.Datum, error) {
val := tree.MustBeDBitArray(args[0])
position := tree.MustBeDInt(args[1])

// Checking whether index asked is inside array of bits.
if position < 0 || uint(position) >= val.BitLen() {
return nil, pgerror.Newf(
pgcode.ArraySubscript, "bit index %d out of valid range (0..%d)", position, val.BitLen()-1)
}
return tree.NewDInt(tree.DInt(val.BitArray.String()[position] - '0')), nil
},
Info: "extract a particular bit from a given array of bits",
}),

// 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{
{"val", types.VarBit},
{"position", types.Int},
{"toSet", types.Int},
},
ReturnType: tree.FixedReturnType(types.VarBit),
Fn: func(_ *tree.EvalContext, args tree.Datums) (tree.Datum, error) {
val := tree.MustBeDBitArray(args[0])
position := tree.MustBeDInt(args[1])
toSet := tree.MustBeDInt(args[2])

// Checking whether index asked is inside array of bits.
if position < 0 || uint(position) >= val.BitLen() {
return nil, pgerror.Newf(
pgcode.ArraySubscript, "bit index %d out of valid range (0..%d)", position, val.BitLen()-1)
}
// Converted BitArray to rune format, and update the given index.
encodedString := []rune(val.BitArray.String())
encodedString[position] = rune('0' + toSet)

return tree.ParseDBitArray(string(encodedString))
},
Info: "Set particular bit in a given array of bits",
}),

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

0 comments on commit a356203

Please sign in to comment.