mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 10:02:43 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			298 lines
		
	
	
	
		
			8.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			298 lines
		
	
	
	
		
			8.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2021, Jan de Visser <jan@de-visser.net>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <AK/Badge.h>
 | |
| #include <AK/ByteBuffer.h>
 | |
| #include <AK/ScopeGuard.h>
 | |
| #include <AK/String.h>
 | |
| #include <AK/Variant.h>
 | |
| #include <LibSQL/Forward.h>
 | |
| #include <LibSQL/Serializer.h>
 | |
| #include <LibSQL/TupleDescriptor.h>
 | |
| #include <LibSQL/Type.h>
 | |
| #include <string.h>
 | |
| 
 | |
| namespace SQL {
 | |
| 
 | |
| class Value;
 | |
| 
 | |
| class BaseImpl {
 | |
| public:
 | |
|     explicit BaseImpl(SQLType type = SQLType::Null)
 | |
|         : m_type(type)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     [[nodiscard]] SQLType type() const { return m_type; }
 | |
|     [[nodiscard]] String type_name() const { return SQLType_name(type()); }
 | |
| 
 | |
| private:
 | |
|     SQLType m_type { SQLType::Null };
 | |
| };
 | |
| 
 | |
| class NullImpl : public BaseImpl {
 | |
| public:
 | |
|     explicit NullImpl()
 | |
|         : BaseImpl(SQLType::Null)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     [[nodiscard]] static bool is_null() { return true; }
 | |
|     [[nodiscard]] static String to_string() { return "(null)"; }
 | |
|     [[nodiscard]] static Optional<int> to_int() { return {}; }
 | |
|     [[nodiscard]] static Optional<double> to_double() { return {}; }
 | |
|     [[nodiscard]] static Optional<bool> to_bool() { return {}; }
 | |
|     [[nodiscard]] static bool to_vector(Vector<Value>&) { return false; }
 | |
|     static void assign(Value const&) { }
 | |
|     static void assign_string(String const&) { }
 | |
|     static void assign_int(int) { }
 | |
|     static void assign_double(double) { }
 | |
|     static void assign_bool(bool) { }
 | |
|     static void assign_vector(Vector<Value> const&) { }
 | |
|     [[nodiscard]] static size_t length() { return 0; }
 | |
|     [[nodiscard]] static bool can_cast(Value const&);
 | |
|     [[nodiscard]] static int compare(Value const&);
 | |
|     static void serialize(Serializer&) { }
 | |
|     static void deserialize(Serializer&) { }
 | |
|     [[nodiscard]] static u32 hash() { return 0; }
 | |
| };
 | |
| 
 | |
| template<typename T>
 | |
| class Impl : public BaseImpl {
 | |
| public:
 | |
|     [[nodiscard]] bool is_null() const
 | |
|     {
 | |
|         return !m_value.has_value();
 | |
|     }
 | |
| 
 | |
|     [[nodiscard]] T const& value() const
 | |
|     {
 | |
|         VERIFY(m_value.has_value());
 | |
|         return m_value.value();
 | |
|     }
 | |
| 
 | |
|     [[nodiscard]] size_t length() const
 | |
|     {
 | |
|         return sizeof(T);
 | |
|     }
 | |
| 
 | |
|     void serialize(Serializer& serializer) const
 | |
|     {
 | |
|         serializer.serialize(value());
 | |
|     }
 | |
| 
 | |
|     void deserialize(Serializer& serializer)
 | |
|     {
 | |
|         T value;
 | |
|         serializer.deserialize_to(value);
 | |
|         m_value = value;
 | |
|     }
 | |
| 
 | |
| protected:
 | |
|     explicit Impl(SQLType sql_type)
 | |
|         : BaseImpl(sql_type)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     Optional<T> m_value {};
 | |
| };
 | |
| 
 | |
| class TextImpl : public Impl<String> {
 | |
| public:
 | |
|     explicit TextImpl()
 | |
|         : Impl(SQLType::Text)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     [[nodiscard]] String to_string() const;
 | |
|     [[nodiscard]] Optional<int> to_int() const;
 | |
|     [[nodiscard]] Optional<double> to_double() const;
 | |
|     [[nodiscard]] Optional<bool> to_bool() const;
 | |
|     [[nodiscard]] static bool to_vector(Vector<Value>&) { return false; }
 | |
|     void assign(Value const&);
 | |
|     void assign_string(String const&);
 | |
|     void assign_int(int);
 | |
|     void assign_double(double);
 | |
|     void assign_bool(bool);
 | |
|     void assign_vector(Vector<Value> const&) { m_value = {}; }
 | |
|     [[nodiscard]] size_t length() const;
 | |
|     [[nodiscard]] static bool can_cast(Value const&) { return true; }
 | |
|     [[nodiscard]] int compare(Value const& other) const;
 | |
|     [[nodiscard]] u32 hash() const;
 | |
| };
 | |
| 
 | |
| class IntegerImpl : public Impl<int> {
 | |
| public:
 | |
|     IntegerImpl()
 | |
|         : Impl(SQLType::Integer)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     [[nodiscard]] String to_string() const;
 | |
|     [[nodiscard]] Optional<int> to_int() const;
 | |
|     [[nodiscard]] Optional<double> to_double() const;
 | |
|     [[nodiscard]] Optional<bool> to_bool() const;
 | |
|     [[nodiscard]] static bool to_vector(Vector<Value>&) { return false; }
 | |
|     void assign(Value const&);
 | |
|     void assign_string(String const&);
 | |
|     void assign_int(int);
 | |
|     void assign_double(double);
 | |
|     void assign_bool(bool);
 | |
|     void assign_vector(Vector<Value> const&) { m_value = {}; }
 | |
|     [[nodiscard]] static bool can_cast(Value const&);
 | |
|     [[nodiscard]] int compare(Value const& other) const;
 | |
|     [[nodiscard]] u32 hash() const;
 | |
| };
 | |
| 
 | |
| class FloatImpl : public Impl<double> {
 | |
| public:
 | |
|     explicit FloatImpl()
 | |
|         : Impl(SQLType::Float)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     [[nodiscard]] String to_string() const;
 | |
|     [[nodiscard]] Optional<int> to_int() const;
 | |
|     [[nodiscard]] Optional<double> to_double() const;
 | |
|     [[nodiscard]] Optional<bool> to_bool() const;
 | |
|     [[nodiscard]] static bool to_vector(Vector<Value>&) { return false; }
 | |
|     void assign(Value const&);
 | |
|     void assign_string(String const&);
 | |
|     void assign_int(int);
 | |
|     void assign_double(double);
 | |
|     void assign_bool(bool) { m_value = {}; }
 | |
|     void assign_vector(Vector<Value> const&) { m_value = {}; }
 | |
|     [[nodiscard]] static bool can_cast(Value const&);
 | |
|     [[nodiscard]] int compare(Value const& other) const;
 | |
| 
 | |
|     // Using floats in hash functions is a bad idea. Let's disable that for now.
 | |
|     [[nodiscard]] static u32 hash() { VERIFY_NOT_REACHED(); }
 | |
| };
 | |
| 
 | |
| class BooleanImpl : public Impl<bool> {
 | |
| public:
 | |
|     explicit BooleanImpl()
 | |
|         : Impl(SQLType::Boolean)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     [[nodiscard]] String to_string() const;
 | |
|     [[nodiscard]] Optional<int> to_int() const;
 | |
|     [[nodiscard]] static Optional<double> to_double();
 | |
|     [[nodiscard]] Optional<bool> to_bool() const;
 | |
|     [[nodiscard]] static bool to_vector(Vector<Value>&) { return false; }
 | |
|     void assign(Value const&);
 | |
|     void assign_string(String const&);
 | |
|     void assign_int(int);
 | |
|     void assign_double(double);
 | |
|     void assign_bool(bool);
 | |
|     void assign_vector(Vector<Value> const&) { m_value = {}; }
 | |
|     [[nodiscard]] static bool can_cast(Value const&);
 | |
|     [[nodiscard]] int compare(Value const& other) const;
 | |
|     [[nodiscard]] u32 hash() const;
 | |
| };
 | |
| 
 | |
| using BaseTypeImpl = Variant<NullImpl, TextImpl, IntegerImpl, FloatImpl, BooleanImpl>;
 | |
| 
 | |
| class ContainerValueImpl : public Impl<Vector<BaseTypeImpl>> {
 | |
| public:
 | |
|     virtual ~ContainerValueImpl() = default;
 | |
| 
 | |
|     [[nodiscard]] String to_string() const;
 | |
|     [[nodiscard]] static Optional<int> to_int() { return {}; }
 | |
|     [[nodiscard]] static Optional<double> to_double() { return {}; }
 | |
|     [[nodiscard]] static Optional<bool> to_bool() { return {}; }
 | |
|     [[nodiscard]] bool to_vector(Vector<Value>&) const;
 | |
|     void assign_string(String const&) { m_value = {}; }
 | |
|     void assign_int(int) { m_value = {}; }
 | |
|     void assign_double(double) { m_value = {}; }
 | |
|     void assign_bool(bool) { m_value = {}; }
 | |
|     void assign_vector(Vector<Value> const&);
 | |
|     [[nodiscard]] u32 hash() const;
 | |
| 
 | |
|     virtual bool validate_before_assignment(Vector<Value> const&) { return true; }
 | |
|     virtual bool validate(BaseTypeImpl const&) { return true; }
 | |
|     virtual bool validate_after_assignment() { return true; }
 | |
|     [[nodiscard]] Vector<String> to_string_vector() const;
 | |
|     [[nodiscard]] size_t length() const;
 | |
|     [[nodiscard]] size_t size() const { return is_null() ? 0 : value().size(); }
 | |
|     bool append(Value const&);
 | |
|     bool append(BaseTypeImpl const& value);
 | |
|     void serialize_values(Serializer&) const;
 | |
|     void deserialize_values(Serializer&);
 | |
| 
 | |
| protected:
 | |
|     explicit ContainerValueImpl(SQLType sql_type)
 | |
|         : Impl(sql_type)
 | |
|     {
 | |
|     }
 | |
| };
 | |
| 
 | |
| class TupleImpl : public ContainerValueImpl {
 | |
| public:
 | |
|     explicit TupleImpl(NonnullRefPtr<TupleDescriptor> const& descriptor)
 | |
|         : ContainerValueImpl(SQLType::Tuple)
 | |
|         , m_descriptor(descriptor)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     explicit TupleImpl()
 | |
|         : ContainerValueImpl(SQLType::Tuple)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     void assign(Value const&);
 | |
|     [[nodiscard]] size_t length() const;
 | |
|     [[nodiscard]] bool can_cast(Value const&) const;
 | |
|     [[nodiscard]] int compare(Value const& other) const;
 | |
|     [[nodiscard]] Optional<bool> to_bool() const;
 | |
| 
 | |
|     virtual bool validate_before_assignment(Vector<Value> const&) override;
 | |
|     virtual bool validate(BaseTypeImpl const&) override;
 | |
|     virtual bool validate_after_assignment() override;
 | |
|     void serialize(Serializer&) const;
 | |
|     void deserialize(Serializer&);
 | |
| 
 | |
| private:
 | |
|     void infer_descriptor();
 | |
|     void extend_descriptor(Value const&);
 | |
|     RefPtr<TupleDescriptor> m_descriptor;
 | |
|     bool m_descriptor_inferred { false };
 | |
| };
 | |
| 
 | |
| class ArrayImpl : public ContainerValueImpl {
 | |
| public:
 | |
|     explicit ArrayImpl(SQLType element_type, Optional<size_t> const& max_size = {})
 | |
|         : ContainerValueImpl(SQLType::Array)
 | |
|         , m_element_type(element_type)
 | |
|         , m_max_size(max_size)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     explicit ArrayImpl()
 | |
|         : ContainerValueImpl(SQLType::Array)
 | |
|         , m_element_type(SQLType::Null)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     void assign(Value const&);
 | |
|     [[nodiscard]] size_t length() const;
 | |
|     [[nodiscard]] bool can_cast(Value const&) const;
 | |
|     [[nodiscard]] int compare(Value const& other) const;
 | |
|     void serialize(Serializer&) const;
 | |
|     void deserialize(Serializer&);
 | |
|     virtual bool validate(BaseTypeImpl const&) override;
 | |
| 
 | |
| private:
 | |
|     SQLType m_element_type { SQLType::Text };
 | |
|     Optional<size_t> m_max_size {};
 | |
| };
 | |
| 
 | |
| using ValueTypeImpl = Variant<NullImpl, TextImpl, IntegerImpl, FloatImpl, BooleanImpl, TupleImpl, ArrayImpl>;
 | |
| 
 | |
| }
 | 
