Serenity Operating System
1/*
2 * Copyright (c) 2021, Jan de Visser <jan@de-visser.net>
3 * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8#pragma once
9
10#include <AK/Checked.h>
11#include <AK/DeprecatedString.h>
12#include <AK/Format.h>
13#include <AK/Optional.h>
14#include <AK/StringView.h>
15#include <AK/Variant.h>
16#include <AK/Vector.h>
17#include <LibIPC/Forward.h>
18#include <LibSQL/Forward.h>
19#include <LibSQL/Result.h>
20#include <LibSQL/Type.h>
21#include <math.h>
22
23namespace SQL {
24
25template<typename T>
26concept Boolean = SameAs<RemoveCVReference<T>, bool>;
27
28template<typename T>
29concept Integer = (Integral<T> && !Boolean<T>);
30
31/**
32 * A `Value` is an atomic piece of SQL data`. A `Value` has a basic type
33 * (Text/String, Integer, Float, etc). Richer types are implemented in higher
34 * level layers, but the resulting data is stored in these `Value` objects.
35 */
36class Value {
37 template<Integer T>
38 using IntegerType = Conditional<IsSigned<T>, i64, u64>;
39
40public:
41 explicit Value(SQLType sql_type = SQLType::Null);
42 explicit Value(DeprecatedString);
43 explicit Value(double);
44 Value(Value const&);
45 Value(Value&&);
46 ~Value();
47
48 explicit Value(Integer auto value)
49 : m_type(SQLType::Integer)
50 , m_value(static_cast<IntegerType<decltype(value)>>(value))
51 {
52 }
53
54 explicit Value(Boolean auto value)
55 : m_type(SQLType::Boolean)
56 , m_value(value)
57 {
58 }
59
60 static ResultOr<Value> create_tuple(NonnullRefPtr<TupleDescriptor>);
61 static ResultOr<Value> create_tuple(Vector<Value>);
62
63 [[nodiscard]] SQLType type() const;
64 [[nodiscard]] StringView type_name() const;
65 [[nodiscard]] bool is_type_compatible_with(SQLType) const;
66 [[nodiscard]] bool is_null() const;
67 [[nodiscard]] bool is_int() const;
68
69 [[nodiscard]] auto const& value() const
70 {
71 VERIFY(m_value.has_value());
72 return *m_value;
73 }
74
75 [[nodiscard]] DeprecatedString to_deprecated_string() const;
76 [[nodiscard]] Optional<double> to_double() const;
77 [[nodiscard]] Optional<bool> to_bool() const;
78 [[nodiscard]] Optional<Vector<Value>> to_vector() const;
79
80 template<Integer T>
81 [[nodiscard]] Optional<T> to_int() const
82 {
83 if (is_null())
84 return {};
85
86 return m_value->visit(
87 [](DeprecatedString const& value) -> Optional<T> {
88 if constexpr (IsSigned<T>)
89 return value.to_int<T>();
90 else
91 return value.to_uint<T>();
92 },
93 [](Integer auto value) -> Optional<T> {
94 if (!AK::is_within_range<T>(value))
95 return {};
96 return static_cast<T>(value);
97 },
98 [](double value) -> Optional<T> {
99 if (!AK::is_within_range<T>(value))
100 return {};
101 return static_cast<T>(round(value));
102 },
103 [](bool value) -> Optional<T> { return static_cast<T>(value); },
104 [](TupleValue const&) -> Optional<T> { return {}; });
105 }
106
107 Value& operator=(Value);
108 Value& operator=(DeprecatedString);
109 Value& operator=(double);
110
111 Value& operator=(Integer auto value)
112 {
113 m_type = SQLType::Integer;
114 m_value = static_cast<IntegerType<decltype(value)>>(value);
115 return *this;
116 }
117
118 ResultOr<void> assign_tuple(NonnullRefPtr<TupleDescriptor>);
119 ResultOr<void> assign_tuple(Vector<Value>);
120
121 Value& operator=(Boolean auto value)
122 {
123 m_type = SQLType::Boolean;
124 m_value = value;
125 return *this;
126 }
127
128 [[nodiscard]] size_t length() const;
129 [[nodiscard]] u32 hash() const;
130 void serialize(Serializer&) const;
131 void deserialize(Serializer&);
132
133 [[nodiscard]] int compare(Value const&) const;
134 bool operator==(Value const&) const;
135 bool operator==(StringView) const;
136 bool operator==(double) const;
137
138 template<Integer T>
139 bool operator==(T value)
140 {
141 return to_int<T>() == value;
142 }
143
144 bool operator!=(Value const&) const;
145 bool operator<(Value const&) const;
146 bool operator<=(Value const&) const;
147 bool operator>(Value const&) const;
148 bool operator>=(Value const&) const;
149
150 ResultOr<Value> add(Value const&) const;
151 ResultOr<Value> subtract(Value const&) const;
152 ResultOr<Value> multiply(Value const&) const;
153 ResultOr<Value> divide(Value const&) const;
154 ResultOr<Value> modulo(Value const&) const;
155 ResultOr<Value> negate() const;
156 ResultOr<Value> shift_left(Value const&) const;
157 ResultOr<Value> shift_right(Value const&) const;
158 ResultOr<Value> bitwise_or(Value const&) const;
159 ResultOr<Value> bitwise_and(Value const&) const;
160 ResultOr<Value> bitwise_not() const;
161
162 [[nodiscard]] TupleElementDescriptor descriptor() const;
163
164private:
165 friend Serializer;
166
167 struct TupleValue {
168 NonnullRefPtr<TupleDescriptor> descriptor;
169 Vector<Value> values;
170 };
171
172 using ValueType = Variant<DeprecatedString, i64, u64, double, bool, TupleValue>;
173
174 static ResultOr<NonnullRefPtr<TupleDescriptor>> infer_tuple_descriptor(Vector<Value> const& values);
175 Value(NonnullRefPtr<TupleDescriptor> descriptor, Vector<Value> values);
176
177 SQLType m_type { SQLType::Null };
178 Optional<ValueType> m_value;
179};
180
181}
182
183template<>
184struct AK::Formatter<SQL::Value> : Formatter<StringView> {
185 ErrorOr<void> format(FormatBuilder& builder, SQL::Value const& value)
186 {
187 return Formatter<StringView>::format(builder, value.to_deprecated_string());
188 }
189};
190
191namespace IPC {
192
193template<>
194ErrorOr<void> encode(Encoder&, SQL::Value const&);
195
196template<>
197ErrorOr<SQL::Value> decode(Decoder&);
198
199}