Serenity Operating System
1/*
2 * Copyright (c) 2021, Jan de Visser <jan@de-visser.net>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <cstring>
8
9#include <AK/DeprecatedString.h>
10#include <AK/StringBuilder.h>
11#include <LibSQL/Serializer.h>
12#include <LibSQL/Tuple.h>
13#include <LibSQL/TupleDescriptor.h>
14#include <LibSQL/Value.h>
15
16namespace SQL {
17
18Tuple::Tuple()
19 : m_descriptor(adopt_ref(*new TupleDescriptor))
20 , m_data()
21{
22}
23
24Tuple::Tuple(NonnullRefPtr<TupleDescriptor> const& descriptor, u32 pointer)
25 : m_descriptor(descriptor)
26 , m_data()
27 , m_pointer(pointer)
28{
29 for (auto& element : *descriptor) {
30 m_data.empend(element.type);
31 }
32}
33
34Tuple::Tuple(NonnullRefPtr<TupleDescriptor> const& descriptor, Serializer& serializer)
35 : Tuple(descriptor)
36{
37 deserialize(serializer);
38}
39
40void Tuple::deserialize(Serializer& serializer)
41{
42 dbgln_if(SQL_DEBUG, "deserialize tuple at offset {}", serializer.offset());
43 serializer.deserialize_to<u32>(m_pointer);
44 dbgln_if(SQL_DEBUG, "pointer: {}", m_pointer);
45 auto sz = serializer.deserialize<u32>();
46 m_data.clear();
47 m_descriptor->clear();
48 for (auto ix = 0u; ix < sz; ++ix) {
49 m_descriptor->append(serializer.deserialize<TupleElementDescriptor>());
50 m_data.append(serializer.deserialize<Value>());
51 }
52}
53
54void Tuple::serialize(Serializer& serializer) const
55{
56 VERIFY(m_descriptor->size() == m_data.size());
57 dbgln_if(SQL_DEBUG, "Serializing tuple pointer {}", pointer());
58 serializer.serialize<u32>(pointer());
59 serializer.serialize<u32>((u32)m_descriptor->size());
60 for (auto ix = 0u; ix < m_descriptor->size(); ix++) {
61 auto& key_part = m_data[ix];
62 serializer.serialize<TupleElementDescriptor>((*m_descriptor)[ix]);
63 serializer.serialize<Value>(key_part);
64 }
65}
66
67Tuple::Tuple(Tuple const& other)
68 : m_descriptor(other.m_descriptor)
69 , m_data()
70{
71 copy_from(other);
72}
73
74Tuple& Tuple::operator=(Tuple const& other)
75{
76 if (this != &other) {
77 copy_from(other);
78 }
79 return *this;
80}
81
82Optional<size_t> Tuple::index_of(StringView name) const
83{
84 for (auto ix = 0u; ix < m_descriptor->size(); ix++) {
85 auto& part = (*m_descriptor)[ix];
86 if (part.name == name) {
87 return ix;
88 }
89 }
90 return {};
91}
92
93Value const& Tuple::operator[](DeprecatedString const& name) const
94{
95 auto index = index_of(name);
96 VERIFY(index.has_value());
97 return (*this)[index.value()];
98}
99
100Value& Tuple::operator[](DeprecatedString const& name)
101{
102 auto index = index_of(name);
103 VERIFY(index.has_value());
104 return (*this)[index.value()];
105}
106
107void Tuple::append(Value const& value)
108{
109 VERIFY(descriptor()->size() >= size());
110 if (descriptor()->size() == size()) {
111 descriptor()->append(value.descriptor());
112 }
113 m_data.append(value);
114}
115
116Tuple& Tuple::operator+=(Value const& value)
117{
118 append(value);
119 return *this;
120}
121
122void Tuple::extend(Tuple const& other)
123{
124 VERIFY((descriptor()->size() == size()) || (descriptor()->size() >= size() + other.size()));
125 if (descriptor()->size() == size()) {
126 descriptor()->extend(other.descriptor());
127 }
128 m_data.extend(other.m_data);
129}
130
131bool Tuple::is_compatible(Tuple const& other) const
132{
133 if ((m_descriptor->size() == 0) && (other.m_descriptor->size() == 0)) {
134 return true;
135 }
136 if (m_descriptor->size() != other.m_descriptor->size()) {
137 return false;
138 }
139 for (auto ix = 0u; ix < m_descriptor->size(); ix++) {
140 auto& my_part = (*m_descriptor)[ix];
141 auto& other_part = (*other.m_descriptor)[ix];
142 if (my_part.type != other_part.type) {
143 return false;
144 }
145 if (my_part.order != other_part.order) {
146 return false;
147 }
148 }
149 return true;
150}
151
152size_t Tuple::length() const
153{
154 size_t len = 2 * sizeof(u32);
155 for (auto ix = 0u; ix < m_descriptor->size(); ix++) {
156 auto& descriptor = (*m_descriptor)[ix];
157 auto& value = m_data[ix];
158 len += descriptor.length();
159 len += value.length();
160 }
161 return len;
162}
163
164DeprecatedString Tuple::to_deprecated_string() const
165{
166 StringBuilder builder;
167 for (auto& part : m_data) {
168 if (!builder.is_empty()) {
169 builder.append('|');
170 }
171 builder.append(part.to_deprecated_string());
172 }
173 if (pointer() != 0) {
174 builder.appendff(":{}", pointer());
175 }
176 return builder.to_deprecated_string();
177}
178
179void Tuple::copy_from(Tuple const& other)
180{
181 if (*m_descriptor != *other.m_descriptor) {
182 m_descriptor->clear();
183 for (TupleElementDescriptor const& part : *other.m_descriptor) {
184 m_descriptor->append(part);
185 }
186 }
187 m_data.clear();
188 for (auto& part : other.m_data) {
189 m_data.append(part);
190 }
191 m_pointer = other.pointer();
192}
193
194int Tuple::compare(Tuple const& other) const
195{
196 auto num_values = min(m_data.size(), other.m_data.size());
197 VERIFY(num_values > 0);
198 for (auto ix = 0u; ix < num_values; ix++) {
199 auto ret = m_data[ix].compare(other.m_data[ix]);
200 if (ret != 0) {
201 if ((ix < m_descriptor->size()) && (*m_descriptor)[ix].order == Order::Descending)
202 ret = -ret;
203 return ret;
204 }
205 }
206 return 0;
207}
208
209int Tuple::match(Tuple const& other) const
210{
211 auto other_index = 0u;
212 for (auto const& part : *other.descriptor()) {
213 auto const& other_value = other[other_index];
214 if (other_value.is_null())
215 return 0;
216 auto my_index = index_of(part.name);
217 if (!my_index.has_value())
218 return -1;
219 auto ret = m_data[my_index.value()].compare(other_value);
220 if (ret != 0)
221 return ((*m_descriptor)[my_index.value()].order == Order::Descending) ? -ret : ret;
222 other_index++;
223 }
224 return 0;
225}
226
227u32 Tuple::hash() const
228{
229 u32 ret = 0u;
230 for (auto& value : m_data) {
231 // This is an extension of the pair_int_hash function from AK/HashFunctions.h:
232 if (!ret)
233 ret = value.hash();
234 else
235 ret = int_hash((ret * 209) ^ (value.hash() * 413));
236 }
237 return ret;
238}
239
240}