Skip to content

Commit

Permalink
Merge #46875
Browse files Browse the repository at this point in the history
46875: sql: allow strpos() builtin function to support bit and bytes array r=otan a=abhishek20123g

Fixes #45849

This commit modified strpos builtin function to allow it to
support bit and byte array and add their respective testcases.

This PR creates separate overloads for both bit and bytes as:
strpos(varbit, varbit)
strpos(bytes, bytes)
since POSITION is an alias for strpos, at the parser level.
Therefore this PR affect POSITION too.

Release justification: low-risk change to existing functionality.

Release note (sql change): This PR modified strpos() function
to allow it support bit and byte array.

Co-authored-by: abhishek20123g <[email protected]>
  • Loading branch information
craig[bot] and abhishek20123g committed Apr 7, 2020
2 parents 2032daf + cc1d400 commit 6365a3f
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 1 deletion.
4 changes: 4 additions & 0 deletions docs/generated/sql/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -1030,9 +1030,13 @@ has no relationship with the commit order of concurrent transactions.</p>
<tr><td><a name="split_part"></a><code>split_part(input: <a href="string.html">string</a>, delimiter: <a href="string.html">string</a>, return_index_pos: <a href="int.html">int</a>) &rarr; <a href="string.html">string</a></code></td><td><span class="funcdesc"><p>Splits <code>input</code> on <code>delimiter</code> and return the value in the <code>return_index_pos</code> position (starting at 1).</p>
<p>For example, <code>split_part('123.456.789.0','.',3)</code>returns <code>789</code>.</p>
</span></td></tr>
<tr><td><a name="strpos"></a><code>strpos(input: <a href="bytes.html">bytes</a>, find: <a href="bytes.html">bytes</a>) &rarr; <a href="int.html">int</a></code></td><td><span class="funcdesc"><p>Calculates the position where the byte subarray <code>find</code> begins in <code>input</code>.</p>
</span></td></tr>
<tr><td><a name="strpos"></a><code>strpos(input: <a href="string.html">string</a>, find: <a href="string.html">string</a>) &rarr; <a href="int.html">int</a></code></td><td><span class="funcdesc"><p>Calculates the position where the string <code>find</code> begins in <code>input</code>.</p>
<p>For example, <code>strpos('doggie', 'gie')</code> returns <code>4</code>.</p>
</span></td></tr>
<tr><td><a name="strpos"></a><code>strpos(input: varbit, find: varbit) &rarr; <a href="int.html">int</a></code></td><td><span class="funcdesc"><p>Calculates the position where the bit subarray <code>find</code> begins in <code>input</code>.</p>
</span></td></tr>
<tr><td><a name="substr"></a><code>substr(input: <a href="bytes.html">bytes</a>, start_pos: <a href="int.html">int</a>) &rarr; <a href="bytes.html">bytes</a></code></td><td><span class="funcdesc"><p>Returns a byte subarray of <code>input</code> starting at <code>start_pos</code> (count starts at 1).</p>
</span></td></tr>
<tr><td><a name="substr"></a><code>substr(input: <a href="bytes.html">bytes</a>, start_pos: <a href="int.html">int</a>, length: <a href="int.html">int</a>) &rarr; <a href="bytes.html">bytes</a></code></td><td><span class="funcdesc"><p>Returns a byte subarray of <code>input</code> starting at <code>start_pos</code> (count starts at 1) and including up to <code>length</code> characters.</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 @@ -459,6 +459,31 @@ SELECT strpos('💩high', 'ig')
----
3

query III
SELECT strpos(B'00001111', B'1111'), strpos(B'', B''), strpos(B'0000111', B'1111')
----
5 1 0

query I
SELECT strpos('000001'::varbit, '1'::varbit)
----
6

query I
SELECT position(B'100' in B'100101')
----
1

query III
SELECT strpos(b'\x61\145aabc', b'abc'), strpos(b'', b''), strpos(b'ttt\x61\x61c', b'abc')
----
4 1 0

query I
SELECT position('\x616263'::bytea in 'abc'::bytea)
----
1

query I
SELECT position('ig' in 'high')
----
Expand Down
50 changes: 49 additions & 1 deletion pkg/sql/sem/builtins/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -975,7 +975,23 @@ var builtins = map[string]builtinDefinition{

return tree.NewDInt(tree.DInt(utf8.RuneCountInString(s[:index]) + 1)), nil
}, types.Int, "Calculates the position where the string `find` begins in `input`. \n\nFor"+
" example, `strpos('doggie', 'gie')` returns `4`.")),
" example, `strpos('doggie', 'gie')` returns `4`."),
bitsOverload2("input", "find",
func(_ *tree.EvalContext, bitString, bitSubstring *tree.DBitArray) (tree.Datum, error) {
index := strings.Index(bitString.BitArray.String(), bitSubstring.BitArray.String())
if index < 0 {
return tree.DZero, nil
}
return tree.NewDInt(tree.DInt(index + 1)), nil
}, types.Int, "Calculates the position where the bit subarray `find` begins in `input`."),
bytesOverload2("input", "find",
func(_ *tree.EvalContext, byteString, byteSubstring string) (tree.Datum, error) {
index := strings.Index(byteString, byteSubstring)
if index < 0 {
return tree.DZero, nil
}
return tree.NewDInt(tree.DInt(index + 1)), nil
}, types.Int, "Calculates the position where the byte subarray `find` begins in `input`.")),

"overlay": makeBuiltin(defProps(),
tree.Overload{
Expand Down Expand Up @@ -4714,6 +4730,22 @@ func bytesOverload1(
}
}

func bytesOverload2(
a, b string,
f func(*tree.EvalContext, string, string) (tree.Datum, error),
returnType *types.T,
info string,
) tree.Overload {
return tree.Overload{
Types: tree.ArgTypes{{a, types.Bytes}, {b, types.Bytes}},
ReturnType: tree.FixedReturnType(returnType),
Fn: func(evalCtx *tree.EvalContext, args tree.Datums) (tree.Datum, error) {
return f(evalCtx, string(*args[0].(*tree.DBytes)), string(*args[1].(*tree.DBytes)))
},
Info: info,
}
}

func bitsOverload1(
f func(*tree.EvalContext, *tree.DBitArray) (tree.Datum, error), returnType *types.T, info string,
) tree.Overload {
Expand All @@ -4727,6 +4759,22 @@ func bitsOverload1(
}
}

func bitsOverload2(
a, b string,
f func(*tree.EvalContext, *tree.DBitArray, *tree.DBitArray) (tree.Datum, error),
returnType *types.T,
info string,
) tree.Overload {
return tree.Overload{
Types: tree.ArgTypes{{a, types.VarBit}, {b, types.VarBit}},
ReturnType: tree.FixedReturnType(returnType),
Fn: func(evalCtx *tree.EvalContext, args tree.Datums) (tree.Datum, error) {
return f(evalCtx, args[0].(*tree.DBitArray), args[1].(*tree.DBitArray))
},
Info: info,
}
}

// feedHash returns true if it encounters any non-Null datum.
func feedHash(h hash.Hash, args tree.Datums) (bool, error) {
var nonNullSeen bool
Expand Down

0 comments on commit 6365a3f

Please sign in to comment.