1#include "duckdb/common/exception.hpp"
2#include "duckdb/common/operator/comparison_operators.hpp"
3#include "duckdb/common/value_operations/value_operations.hpp"
4
5using namespace duckdb;
6using namespace std;
7
8//===--------------------------------------------------------------------===//
9// Comparison Operations
10//===--------------------------------------------------------------------===//
11template <class OP> static bool templated_boolean_operation(const Value &left, const Value &right) {
12 if (left.type != right.type) {
13 TypeId left_cast = TypeId::INVALID, right_cast = TypeId::INVALID;
14 if (TypeIsNumeric(left.type) && TypeIsNumeric(right.type)) {
15 if (left.type < right.type) {
16 left_cast = right.type;
17 } else {
18 right_cast = left.type;
19 }
20 } else if (left.type == TypeId::BOOL) {
21 right_cast = TypeId::BOOL;
22 } else if (right.type == TypeId::BOOL) {
23 left_cast = TypeId::BOOL;
24 }
25 if (left_cast != TypeId::INVALID) {
26 return templated_boolean_operation<OP>(left.CastAs(left_cast), right);
27 } else if (right_cast != TypeId::INVALID) {
28 return templated_boolean_operation<OP>(left, right.CastAs(right_cast));
29 }
30 return false;
31 }
32 switch (left.type) {
33 case TypeId::BOOL:
34 return OP::Operation(left.value_.boolean, right.value_.boolean);
35 case TypeId::INT8:
36 return OP::Operation(left.value_.tinyint, right.value_.tinyint);
37 case TypeId::INT16:
38 return OP::Operation(left.value_.smallint, right.value_.smallint);
39 case TypeId::INT32:
40 return OP::Operation(left.value_.integer, right.value_.integer);
41 case TypeId::INT64:
42 return OP::Operation(left.value_.bigint, right.value_.bigint);
43 case TypeId::POINTER:
44 return OP::Operation(left.value_.pointer, right.value_.pointer);
45 case TypeId::HASH:
46 return OP::Operation(left.value_.hash, right.value_.hash);
47 case TypeId::FLOAT:
48 return OP::Operation(left.value_.float_, right.value_.float_);
49 case TypeId::DOUBLE:
50 return OP::Operation(left.value_.double_, right.value_.double_);
51 case TypeId::VARCHAR:
52 return OP::Operation(left.str_value, right.str_value);
53 case TypeId::STRUCT: {
54 for (idx_t i = 0; i < left.struct_value.size(); i++) {
55 if (i >= right.struct_value.size() || left.struct_value[i].first != right.struct_value[i].first ||
56 left.struct_value[i].second != left.struct_value[i].second) {
57 return false;
58 }
59 }
60 return true;
61 }
62 case TypeId::LIST: {
63 return left.list_value == right.list_value;
64 }
65 default:
66 throw NotImplementedException("Unimplemented type");
67 }
68}
69
70bool ValueOperations::Equals(const Value &left, const Value &right) {
71 if (left.is_null && right.is_null) {
72 return true;
73 }
74 if (left.is_null != right.is_null) {
75 return false;
76 }
77 return templated_boolean_operation<duckdb::Equals>(left, right);
78}
79
80bool ValueOperations::NotEquals(const Value &left, const Value &right) {
81 return !ValueOperations::Equals(left, right);
82}
83
84bool ValueOperations::GreaterThan(const Value &left, const Value &right) {
85 if (left.is_null && right.is_null) {
86 return false;
87 } else if (right.is_null) {
88 return true;
89 } else if (left.is_null) {
90 return false;
91 }
92 return templated_boolean_operation<duckdb::GreaterThan>(left, right);
93}
94
95bool ValueOperations::GreaterThanEquals(const Value &left, const Value &right) {
96 if (left.is_null && right.is_null) {
97 return true;
98 } else if (right.is_null) {
99 return true;
100 } else if (left.is_null) {
101 return false;
102 }
103 return templated_boolean_operation<duckdb::GreaterThanEquals>(left, right);
104}
105
106bool ValueOperations::LessThan(const Value &left, const Value &right) {
107 return ValueOperations::GreaterThan(right, left);
108}
109
110bool ValueOperations::LessThanEquals(const Value &left, const Value &right) {
111 return ValueOperations::GreaterThanEquals(right, left);
112}
113