diff options
author | Jan de Visser <jan@de-visser.net> | 2021-10-21 18:06:24 -0400 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-10-25 12:59:42 +0200 |
commit | 73fc02365233d7ac0e29728beb129354c8b67c41 (patch) | |
tree | f70497fb8f428776222e4b24069ee78c353738c0 /Userland/Libraries | |
parent | 3618ca242052d56ea20a05d94b6d46951567a8b5 (diff) | |
download | serenity-73fc02365233d7ac0e29728beb129354c8b67c41.zip |
LibSQL: Implement binary operators for Value objects
The behaviour of the various operators is supposed to mimic that of
the same operators in PostgreSQL; the '+' operator for example will
successfully add '98' (string) and 2 (integer), but not 'foo' and 2.
Also removed some redundant const& parameter declarations for
intrinsic types (ints and doubles etc). Passing those by const& doesn't
make a lot of sense.
Diffstat (limited to 'Userland/Libraries')
-rw-r--r-- | Userland/Libraries/LibSQL/Value.cpp | 149 | ||||
-rw-r--r-- | Userland/Libraries/LibSQL/Value.h | 18 |
2 files changed, 161 insertions, 6 deletions
diff --git a/Userland/Libraries/LibSQL/Value.cpp b/Userland/Libraries/LibSQL/Value.cpp index e30e402381..d5fea9d48e 100644 --- a/Userland/Libraries/LibSQL/Value.cpp +++ b/Userland/Libraries/LibSQL/Value.cpp @@ -85,6 +85,12 @@ Value::Value(int integer) assign(integer); } +Value::Value(u32 unsigned_integer) + : Value(SQLType::Integer) +{ + assign(unsigned_integer); +} + Value::Value(double dbl) : Value(SQLType::Float) { @@ -225,17 +231,22 @@ void Value::assign(String const& string_value) m_impl.visit([&](auto& impl) { impl.assign_string(string_value); }); } -void Value::assign(int const& int_value) +void Value::assign(int int_value) { m_impl.visit([&](auto& impl) { impl.assign_int(int_value); }); } -void Value::assign(double const& double_value) +void Value::assign(u32 unsigned_int_value) +{ + m_impl.visit([&](auto& impl) { impl.assign_int(unsigned_int_value); }); +} + +void Value::assign(double double_value) { m_impl.visit([&](auto& impl) { impl.assign_double(double_value); }); } -void Value::assign(bool const& bool_value) +void Value::assign(bool bool_value) { m_impl.visit([&](auto& impl) { impl.assign_bool(bool_value); }); } @@ -377,6 +388,138 @@ bool Value::operator>=(Value const& other) const return compare(other) >= 0; } +Value Value::add(Value const& other) const +{ + if (auto double_maybe = to_double(); double_maybe.has_value()) { + if (auto other_double_maybe = other.to_double(); other_double_maybe.has_value()) + return Value(double_maybe.value() + other_double_maybe.value()); + if (auto int_maybe = other.to_int(); int_maybe.has_value()) + return Value(double_maybe.value() + (double)int_maybe.value()); + VERIFY_NOT_REACHED(); + } + if (auto int_maybe = to_double(); int_maybe.has_value()) { + if (auto other_double_maybe = other.to_double(); other_double_maybe.has_value()) + return Value(other_double_maybe.value() + (double)int_maybe.value()); + if (auto other_int_maybe = other.to_int(); other_int_maybe.has_value()) + return Value(int_maybe.value() + other_int_maybe.value()); + VERIFY_NOT_REACHED(); + } + VERIFY_NOT_REACHED(); +} + +Value Value::subtract(Value const& other) const +{ + if (auto double_maybe = to_double(); double_maybe.has_value()) { + if (auto other_double_maybe = other.to_double(); other_double_maybe.has_value()) + return Value(double_maybe.value() - other_double_maybe.value()); + if (auto int_maybe = other.to_int(); int_maybe.has_value()) + return Value(double_maybe.value() - (double)int_maybe.value()); + VERIFY_NOT_REACHED(); + } + if (auto int_maybe = to_double(); int_maybe.has_value()) { + if (auto other_double_maybe = other.to_double(); other_double_maybe.has_value()) + return Value((double)int_maybe.value() - other_double_maybe.value()); + if (auto other_int_maybe = other.to_int(); other_int_maybe.has_value()) + return Value(int_maybe.value() - other_int_maybe.value()); + VERIFY_NOT_REACHED(); + } + VERIFY_NOT_REACHED(); +} + +Value Value::multiply(Value const& other) const +{ + if (auto double_maybe = to_double(); double_maybe.has_value()) { + if (auto other_double_maybe = other.to_double(); other_double_maybe.has_value()) + return Value(double_maybe.value() * other_double_maybe.value()); + if (auto int_maybe = other.to_int(); int_maybe.has_value()) + return Value(double_maybe.value() * (double)int_maybe.value()); + VERIFY_NOT_REACHED(); + } + if (auto int_maybe = to_double(); int_maybe.has_value()) { + if (auto other_double_maybe = other.to_double(); other_double_maybe.has_value()) + return Value((double)int_maybe.value() * other_double_maybe.value()); + if (auto other_int_maybe = other.to_int(); other_int_maybe.has_value()) + return Value(int_maybe.value() * other_int_maybe.value()); + VERIFY_NOT_REACHED(); + } + VERIFY_NOT_REACHED(); +} + +Value Value::divide(Value const& other) const +{ + if (auto double_maybe = to_double(); double_maybe.has_value()) { + if (auto other_double_maybe = other.to_double(); other_double_maybe.has_value()) + return Value(double_maybe.value() / other_double_maybe.value()); + if (auto int_maybe = other.to_int(); int_maybe.has_value()) + return Value(double_maybe.value() / (double)int_maybe.value()); + VERIFY_NOT_REACHED(); + } + + if (auto int_maybe = to_double(); int_maybe.has_value()) { + if (auto other_double_maybe = other.to_double(); other_double_maybe.has_value()) + return Value((double)int_maybe.value() / other_double_maybe.value()); + if (auto other_int_maybe = other.to_int(); other_int_maybe.has_value()) + return Value(int_maybe.value() / other_int_maybe.value()); + VERIFY_NOT_REACHED(); + } + VERIFY_NOT_REACHED(); +} + +Value Value::modulo(Value const& other) const +{ + auto int_maybe_1 = to_int(); + auto int_maybe_2 = other.to_int(); + if (!int_maybe_1.has_value() || !int_maybe_2.has_value()) { + // TODO Error handling + VERIFY_NOT_REACHED(); + } + return Value(int_maybe_1.value() % int_maybe_2.value()); +} + +Value Value::shift_left(Value const& other) const +{ + auto u32_maybe = to_u32(); + auto num_bytes_maybe = other.to_int(); + if (!u32_maybe.has_value() || !num_bytes_maybe.has_value()) { + // TODO Error handling + VERIFY_NOT_REACHED(); + } + return Value(u32_maybe.value() << num_bytes_maybe.value()); +} + +Value Value::shift_right(Value const& other) const +{ + auto u32_maybe = to_u32(); + auto num_bytes_maybe = other.to_int(); + if (!u32_maybe.has_value() || !num_bytes_maybe.has_value()) { + // TODO Error handling + VERIFY_NOT_REACHED(); + } + return Value(u32_maybe.value() >> num_bytes_maybe.value()); +} + +Value Value::bitwise_or(Value const& other) const +{ + auto u32_maybe_1 = to_u32(); + auto u32_maybe_2 = other.to_u32(); + if (!u32_maybe_1.has_value() || !u32_maybe_2.has_value()) { + // TODO Error handling + VERIFY_NOT_REACHED(); + } + return Value(u32_maybe_1.value() | u32_maybe_2.value()); +} + +Value Value::bitwise_and(Value const& other) const +{ + auto u32_maybe_1 = to_u32(); + auto u32_maybe_2 = other.to_u32(); + if (!u32_maybe_1.has_value() || !u32_maybe_2.has_value()) { + // TODO Error handling + VERIFY_NOT_REACHED(); + } + return Value(u32_maybe_1.value() & u32_maybe_2.value()); +} + void Value::serialize(Serializer& serializer) const { u8 type_flags = (u8)type(); diff --git a/Userland/Libraries/LibSQL/Value.h b/Userland/Libraries/LibSQL/Value.h index 4f10ca2804..28ec19eb03 100644 --- a/Userland/Libraries/LibSQL/Value.h +++ b/Userland/Libraries/LibSQL/Value.h @@ -56,6 +56,7 @@ public: explicit Value(String const&); explicit Value(char const*); explicit Value(int); + explicit Value(u32); explicit Value(double); explicit Value(bool); @@ -84,9 +85,10 @@ public: void assign(Value const& other_value); void assign(String const& string_value); - void assign(int const& int_value); - void assign(double const& double_value); - void assign(bool const& bool_value); + void assign(int int_value); + void assign(u32 unsigned_int_value); + void assign(double double_value); + void assign(bool bool_value); void assign(Vector<Value> const& values); Value& operator=(Value const& other); @@ -116,6 +118,16 @@ public: bool operator>(Value const&) const; bool operator>=(Value const&) const; + Value add(Value const&) const; + Value subtract(Value const&) const; + Value multiply(Value const&) const; + Value divide(Value const&) const; + Value modulo(Value const&) const; + Value shift_left(Value const&) const; + Value shift_right(Value const&) const; + Value bitwise_or(Value const&) const; + Value bitwise_and(Value const&) const; + [[nodiscard]] TupleElementDescriptor descriptor() const { return { "", type(), Order::Ascending }; |