1#include "duckdb/function/scalar/string_functions.hpp"
2#include "duckdb/common/vector_operations/vector_operations.hpp"
3
4#include <ctype.h>
5#include <algorithm>
6
7using namespace std;
8
9namespace duckdb {
10
11static string_t left_scalar_function(Vector &result, const string_t str, int64_t pos, unique_ptr<char[]> &output,
12 idx_t &current_len) {
13 if (pos >= 0) {
14 return SubstringFun::substring_scalar_function(result, str, 1, pos, output, current_len);
15 }
16
17 int64_t num_characters = LengthFun::Length<string_t, int64_t>(str);
18 pos = std::max(int64_t(0), num_characters + pos);
19 return SubstringFun::substring_scalar_function(result, str, 1, pos, output, current_len);
20}
21
22static void left_function(DataChunk &args, ExpressionState &state, Vector &result) {
23 assert(args.column_count() == 2 && args.data[0].type == TypeId::VARCHAR && args.data[1].type == TypeId::INT64);
24 auto &str_vec = args.data[0];
25 auto &pos_vec = args.data[1];
26 idx_t current_len = 0;
27 unique_ptr<char[]> output;
28
29 BinaryExecutor::Execute<string_t, int64_t, string_t, true>(
30 str_vec, pos_vec, result, args.size(),
31 [&](string_t str, int64_t pos) { return left_scalar_function(result, str, pos, output, current_len); });
32}
33
34void LeftFun::RegisterFunction(BuiltinFunctions &set) {
35 set.AddFunction(ScalarFunction("left", {SQLType::VARCHAR, SQLType::BIGINT}, SQLType::VARCHAR, left_function));
36}
37
38static string_t right_scalar_function(Vector &result, const string_t str, int64_t pos, unique_ptr<char[]> &output,
39 idx_t &current_len) {
40 int64_t num_characters = LengthFun::Length<string_t, int64_t>(str);
41 if (pos >= 0) {
42 int64_t len = std::min(num_characters, pos);
43 int64_t start = num_characters - len + 1;
44 return SubstringFun::substring_scalar_function(result, str, start, len, output, current_len);
45 }
46
47 int64_t len = num_characters - std::min(num_characters, -pos);
48 int64_t start = num_characters - len + 1;
49 return SubstringFun::substring_scalar_function(result, str, start, len, output, current_len);
50}
51
52static void right_function(DataChunk &args, ExpressionState &state, Vector &result) {
53 assert(args.column_count() == 2 && args.data[0].type == TypeId::VARCHAR && args.data[1].type == TypeId::INT64);
54 auto &str_vec = args.data[0];
55 auto &pos_vec = args.data[1];
56 idx_t current_len = 0;
57 unique_ptr<char[]> output;
58
59 BinaryExecutor::Execute<string_t, int64_t, string_t, true>(
60 str_vec, pos_vec, result, args.size(),
61 [&](string_t str, int64_t pos) { return right_scalar_function(result, str, pos, output, current_len); });
62}
63
64void RightFun::RegisterFunction(BuiltinFunctions &set) {
65 set.AddFunction(ScalarFunction("right", {SQLType::VARCHAR, SQLType::BIGINT}, SQLType::VARCHAR, right_function));
66}
67
68} // namespace duckdb
69