1#include "duckdb/function/scalar/string_functions.hpp"
2#include "duckdb/common/types/string_type.hpp"
3
4#include "duckdb/common/exception.hpp"
5
6using namespace std;
7
8namespace duckdb {
9
10static bool prefix(const string_t &str, const string_t &pattern);
11
12struct PrefixOperator {
13 template <class TA, class TB, class TR> static inline TR Operation(TA left, TB right) {
14 return prefix(left, right);
15 }
16};
17static bool prefix(const string_t &str, const string_t &pattern) {
18 auto str_size = str.GetSize();
19 auto patt_length = pattern.GetSize();
20 if (patt_length > str_size) {
21 return false;
22 }
23 if (patt_length <= string_t::PREFIX_LENGTH) {
24 // short prefix
25 if (patt_length == 0) {
26 // length = 0, return true
27 return true;
28 }
29
30 // prefix early out
31 const char *str_pref = str.GetPrefix();
32 const char *patt_pref = pattern.GetPrefix();
33 for (idx_t i = 0; i < patt_length; ++i) {
34 if (str_pref[i] != patt_pref[i])
35 return false;
36 }
37 return true;
38 } else {
39 // prefix early out
40 const char *str_pref = str.GetPrefix();
41 const char *patt_pref = pattern.GetPrefix();
42 for (idx_t i = 0; i < string_t::PREFIX_LENGTH; ++i) {
43 if (str_pref[i] != patt_pref[i]) {
44 // early out
45 return false;
46 }
47 }
48 // compare the rest of the prefix
49 const char *str_data = str.GetData();
50 const char *patt_data = pattern.GetData();
51 for (idx_t i = string_t::PREFIX_LENGTH; i < patt_length; ++i) {
52 if (str_data[i] != patt_data[i]) {
53 return false;
54 }
55 }
56 return true;
57 }
58}
59
60ScalarFunction PrefixFun::GetFunction() {
61 return ScalarFunction("prefix", // name of the function
62 {SQLType::VARCHAR, SQLType::VARCHAR}, // argument list
63 SQLType::BOOLEAN, // return type
64 ScalarFunction::BinaryFunction<string_t, string_t, bool, PrefixOperator, true>);
65}
66
67void PrefixFun::RegisterFunction(BuiltinFunctions &set) {
68 set.AddFunction(GetFunction());
69}
70
71} // namespace duckdb
72