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