diff --git a/Cargo.toml b/Cargo.toml
index 29a14d66..a224a7d5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -58,6 +58,7 @@
 	serde_json = "1.0.0"
 	uuid = { version = "1.1.1", features = ["serde", "v4"] }
 	serde_yaml = "0.8.23"
+	enum_dispatch = "0.3.8"
 	lazy_static = "1.4.0"
 
 	# OPTIONAL DEPENDENCIES
diff --git a/src/data/recipe/mod.rs b/src/data/recipe/mod.rs
index 4fe70ebd..bb044371 100644
--- a/src/data/recipe/mod.rs
+++ b/src/data/recipe/mod.rs
@@ -151,7 +151,7 @@ impl RecipeUtilities for PlannedRecipe {
 }
 
 impl Recipe {
-	pub const NULL: Recipe = Recipe::Ingredient(Ingredient::Value(Value::Null));
+	pub const NULL: Recipe = Recipe::Ingredient(Ingredient::Value(Value::NULL));
 	pub const TRUE: Recipe = Recipe::Ingredient(Ingredient::Value(Value::Bool(true)));
 	pub const SINGLE_COLUMN: Recipe = Recipe::Ingredient(Ingredient::Column(0));
 }
diff --git a/src/data/recipe/new.rs b/src/data/recipe/new.rs
index 6b367761..6a459ef0 100644
--- a/src/data/recipe/new.rs
+++ b/src/data/recipe/new.rs
@@ -47,7 +47,7 @@ impl MetaRecipe {
 }
 impl MetaRecipe {
 	pub const NULL: Self = MetaRecipe {
-		recipe: Recipe::Ingredient(Ingredient::Value(Value::Null)),
+		recipe: Recipe::Ingredient(Ingredient::Value(Value::NULL)),
 		meta: RecipeMeta::NEW,
 	};
 	pub const TRUE: Self = MetaRecipe {
diff --git a/src/data/recipe/planned.rs b/src/data/recipe/planned.rs
index 9570aeb7..aed4d52a 100644
--- a/src/data/recipe/planned.rs
+++ b/src/data/recipe/planned.rs
@@ -163,7 +163,7 @@ impl PlannedRecipe {
 							})?
 							.clone())
 					})
-					.unwrap_or(Ok(Value::Null))
+					.unwrap_or(Ok(Value::NULL))
 			})
 			.collect::<Result<Vec<Value>>>()
 	}
diff --git a/src/data/recipe/resolve.rs b/src/data/recipe/resolve.rs
index 83bf27d5..01d72c37 100644
--- a/src/data/recipe/resolve.rs
+++ b/src/data/recipe/resolve.rs
@@ -170,7 +170,7 @@ impl Resolve for Method {
 					let operand = operand.map(|operand| operand.as_solution());
 					let else_result = else_result
 						.map(|else_result| else_result.as_solution())
-						.unwrap_or(Some(Value::Null))
+						.unwrap_or(Some(Value::NULL))
 						.unwrap();
 					if let Some(operand) = operand {
 						let operand = operand.unwrap();
diff --git a/src/data/value/big_endian.rs b/src/data/value/big_endian.rs
index bbb44280..c7186abe 100644
--- a/src/data/value/big_endian.rs
+++ b/src/data/value/big_endian.rs
@@ -1,4 +1,4 @@
-use crate::Value;
+use crate::Null;
 
 pub trait BigEndian {
 	fn to_be_bytes(&self) -> Vec<u8>;
@@ -7,21 +7,39 @@ pub trait BigEndian {
 const SEP: [u8; 1] = [0x00];
 const NULL: [u8; 1] = [0x01];
 
-impl BigEndian for Value {
+impl BigEndian for Null {
 	fn to_be_bytes(&self) -> Vec<u8> {
-		use Value::*;
-		match self {
-			Null => [SEP, NULL].concat(),
-			Bool(v) => [SEP, [if *v { 0x02 } else { 0x01 }]].concat(),
-			I64(v) => [
-				SEP.as_slice(),
-				&[if v.is_positive() { 0x02 } else { 0x01 }],
-				&v.to_be_bytes(),
-			]
-			.concat(),
-			U64(v) => [SEP.as_slice(), &v.to_be_bytes()].concat(),
-			Str(v) => [SEP.as_slice(), v.as_bytes()].concat(),
-			_ => unimplemented!(),
-		}
+		[SEP, NULL].concat()
+	}
+}
+impl BigEndian for bool {
+	fn to_be_bytes(&self) -> Vec<u8> {
+		[SEP, [if *self { 0x02 } else { 0x01 }]].concat()
+	}
+}
+impl BigEndian for i64 {
+	fn to_be_bytes(&self) -> Vec<u8> {
+		[
+			SEP.as_slice(),
+			&[if self.is_positive() { 0x02 } else { 0x01 }],
+			&self.to_be_bytes(),
+		]
+		.concat()
+	}
+}
+impl BigEndian for u64 {
+	fn to_be_bytes(&self) -> Vec<u8> {
+		[SEP.as_slice(), &self.to_be_bytes()].concat()
+	}
+}
+impl BigEndian for String {
+	fn to_be_bytes(&self) -> Vec<u8> {
+		[SEP.as_slice(), self.as_bytes()].concat()
+	}
+}
+
+impl BigEndian for f64 {
+	fn to_be_bytes(&self) -> Vec<u8> {
+		unimplemented!()
 	}
 }
diff --git a/src/data/value/cast.rs b/src/data/value/cast.rs
index c72142ec..c47611b4 100644
--- a/src/data/value/cast.rs
+++ b/src/data/value/cast.rs
@@ -1,140 +1,166 @@
 use {
-	super::{Convert, Value, ValueError, ValueType},
+	super::{Value, ValueError},
 	crate::{Error, Result},
-	chrono::{NaiveDate, NaiveDateTime, NaiveTime, ParseError},
+	//chrono::{NaiveDate, NaiveDateTime, NaiveTime, ParseError},
+	enum_dispatch::enum_dispatch,
 	std::convert::TryInto,
-	thousands::Separable,
+	//thousands::Separable,
 };
 
-pub trait Cast<Output> {
-	fn cast(self) -> Result<Output>;
+#[enum_dispatch(Value)]
+pub trait Cast<Output: Sized>
+where
+	Self: Sized,
+{
+	fn cast(self) -> Result<Output> {
+		Err(Error::Value(ValueError::UnimplementedCast))
+	}
 }
 pub trait CastWithRules<Output> {
 	fn cast_with_rule(self, rule: Self) -> Result<Output>;
 }
 
-fn failed_cast(value: &Value, value_type: ValueType) -> Error {
-	Error::Value(ValueError::FailedCast(value.clone(), value_type))
-}
-fn unimplemented_cast(value: &Value, value_type: ValueType) -> Error {
-	Error::Value(ValueError::FailedCast(value.clone().into(), value_type))
+impl<T> Cast<T> for T {
+	fn cast(self) -> Result<T> {
+		Ok(self)
+	}
 }
 
-// Cores
-impl Cast<bool> for Value {
+/*impl<T> Cast<T> for Null {
+	fn cast(self) -> Result<T> {
+		Err(ValueError::ImpossibleCast.into())
+	}
+}*/
+
+impl Cast<bool> for i64 {
 	fn cast(self) -> Result<bool> {
-		Ok(match self {
-			Value::Bool(value) => value,
-			Value::I64(value) => match value {
-				1 => true,
-				0 => false,
-				_ => return Err(failed_cast(&self, ValueType::Bool)),
-			},
-			Value::F64(value) => {
-				if value.eq(&1.0) {
-					true
-				} else if value.eq(&0.0) {
-					false
-				} else {
-					return Err(failed_cast(&self, ValueType::Bool));
-				}
-			}
-			Value::Str(value) => match value.to_lowercase().as_str() {
-				"true" => true,
-				"false" => false,
-				_ => return Err(failed_cast(&Value::Str(value), ValueType::Bool)),
-			},
-			Value::Null => return Err(failed_cast(&self, ValueType::Bool)),
-			_ => return Err(unimplemented_cast(&self, ValueType::Bool)),
-		})
+		match self {
+			1 => Ok(true),
+			0 => Ok(false),
+			_ => Err(ValueError::ImpossibleCast.into()),
+		}
+	}
+}
+impl Cast<bool> for u64 {
+	fn cast(self) -> Result<bool> {
+		match self {
+			1 => Ok(true),
+			0 => Ok(false),
+			_ => Err(ValueError::ImpossibleCast.into()),
+		}
+	}
+}
+impl Cast<bool> for f64 {
+	fn cast(self) -> Result<bool> {
+		if self.eq(&1.0) {
+			Ok(true)
+		} else if self.eq(&0.0) {
+			Ok(false)
+		} else {
+			Err(ValueError::ImpossibleCast.into())
+		}
+	}
+}
+impl Cast<bool> for String {
+	fn cast(self) -> Result<bool> {
+		match self.to_uppercase().as_str() {
+			"TRUE" => Ok(true),
+			"FALSE" => Ok(false),
+			_ => Err(ValueError::ImpossibleCast.into()),
+		}
 	}
 }
 
-impl Cast<u64> for Value {
+// Cores
+impl Cast<u64> for bool {
 	fn cast(self) -> Result<u64> {
-		Ok(match self {
-			Value::Bool(value) => {
-				if value {
-					1
-				} else {
-					0
-				}
-			}
-			Value::U64(value) => value,
-			Value::I64(value) => value
-				.try_into()
-				.map_err(|_| failed_cast(&self, ValueType::U64))?,
-			Value::F64(value) => (value.trunc() as i64)
-				.try_into()
-				.map_err(|_| failed_cast(&self, ValueType::U64))?,
-			Value::Str(value) => lexical::parse(&value)
-				.map_err(|_| failed_cast(&Value::Str(value), ValueType::U64))?,
-			Value::Null => return Err(failed_cast(&self, ValueType::U64)),
-			_ => return Err(unimplemented_cast(&self, ValueType::U64)),
-		})
+		Ok(if self { 1 } else { 0 })
+	}
+}
+impl Cast<u64> for i64 {
+	fn cast(self) -> Result<u64> {
+		self.try_into()
+			.map_err(|_| Error::Value(ValueError::ImpossibleCast))
+	}
+}
+impl Cast<u64> for f64 {
+	fn cast(self) -> Result<u64> {
+		let int: i64 = self.cast()?;
+		int.cast()
+	}
+}
+impl Cast<u64> for String {
+	fn cast(self) -> Result<u64> {
+		lexical::parse(self).map_err(|_| Error::Value(ValueError::ImpossibleCast))
 	}
 }
 
-impl Cast<i64> for Value {
+impl Cast<i64> for bool {
 	fn cast(self) -> Result<i64> {
-		Ok(match self {
-			Value::Bool(value) => {
-				if value {
-					1
-				} else {
-					0
-				}
-			}
-			Value::U64(value) => value
-				.try_into()
-				.map_err(|_| failed_cast(&self, ValueType::I64))?,
-			Value::I64(value) => value,
-			Value::F64(value) => value.trunc() as i64,
-			Value::Str(value) => lexical::parse(&value)
-				.map_err(|_| failed_cast(&Value::Str(value), ValueType::I64))?,
-			Value::Null => return Err(failed_cast(&self, ValueType::I64)),
-			_ => return Err(unimplemented_cast(&self, ValueType::I64)),
-		})
+		Ok(if self { 1 } else { 0 })
+	}
+}
+impl Cast<i64> for u64 {
+	fn cast(self) -> Result<i64> {
+		self.try_into()
+			.map_err(|_| Error::Value(ValueError::ImpossibleCast))
+	}
+}
+impl Cast<i64> for f64 {
+	fn cast(self) -> Result<i64> {
+		Ok(self.trunc() as i64) // TODO: Better
+	}
+}
+impl Cast<i64> for String {
+	fn cast(self) -> Result<i64> {
+		lexical::parse(self).map_err(|_| Error::Value(ValueError::ImpossibleCast))
 	}
 }
 
-impl Cast<f64> for Value {
+impl Cast<f64> for bool {
 	fn cast(self) -> Result<f64> {
-		Ok(match self {
-			Value::Bool(value) => {
-				if value {
-					1.0
-				} else {
-					0.0
-				}
-			}
-			Value::U64(value) => (value as f64).trunc(),
-			Value::I64(value) => (value as f64).trunc(),
-			Value::F64(value) => value,
-			Value::Str(value) => fast_float::parse(&value)
-				.map_err(|_| failed_cast(&Value::Str(value), ValueType::F64))?,
-			Value::Null => return Err(failed_cast(&self, ValueType::F64)),
-			_ => return Err(unimplemented_cast(&self, ValueType::F64)),
-		})
+		Ok(if self { 1.0 } else { 0.0 })
+	}
+}
+impl Cast<f64> for u64 {
+	fn cast(self) -> Result<f64> {
+		Ok((self as f64).trunc())
+	}
+}
+impl Cast<f64> for i64 {
+	fn cast(self) -> Result<f64> {
+		Ok((self as f64).trunc())
+	}
+}
+impl Cast<f64> for String {
+	fn cast(self) -> Result<f64> {
+		fast_float::parse(self).map_err(|_| Error::Value(ValueError::ImpossibleCast))
+	}
+}
+
+impl Cast<String> for bool {
+	fn cast(self) -> Result<String> {
+		Ok((if self { "TRUE" } else { "FALSE" }).to_string())
+	}
+}
+impl Cast<String> for u64 {
+	fn cast(self) -> Result<String> {
+		Ok(lexical::to_string(self))
 	}
 }
-impl Cast<String> for Value {
+impl Cast<String> for i64 {
 	fn cast(self) -> Result<String> {
-		Ok(match self {
-			Value::Bool(value) => (if value { "true" } else { "false" }).to_string(),
-			Value::U64(value) => lexical::to_string(value),
-			Value::I64(value) => lexical::to_string(value),
-			Value::F64(value) => lexical::to_string(value),
-			Value::Str(value) => value,
-			Value::Timestamp(value) => NaiveDateTime::from_timestamp(value, 0).to_string(),
-			Value::Null => String::from("NULL"),
-			_ => return Err(unimplemented_cast(&self, ValueType::Str)),
-		})
+		Ok(lexical::to_string(self))
+	}
+}
+impl Cast<String> for f64 {
+	fn cast(self) -> Result<String> {
+		Ok(lexical::to_string(self))
 	}
 }
 
 // Utilities
-impl Cast<usize> for Value {
+impl<T: Cast<u64>> Cast<usize> for T {
 	fn cast(self) -> Result<usize> {
 		let int: u64 = self.cast()?;
 		int.try_into()
@@ -142,6 +168,7 @@ impl Cast<usize> for Value {
 	}
 }
 
+/*
 // Non-Core
 impl CastWithRules<bool> for Value {
 	fn cast_with_rule(self, rule: Self) -> Result<bool> {
@@ -167,7 +194,8 @@ impl CastWithRules<f64> for Value {
 		}
 	}
 }
-impl CastWithRules<String> for Value {
+*/
+/*impl CastWithRules<String> for Value {
 	fn cast_with_rule(self, rule: Self) -> Result<String> {
 		match rule {
 			Value::I64(000) | Value::Bool(true) => self.cast(),
@@ -197,8 +225,9 @@ impl CastWithRules<String> for Value {
 			_ => Err(ValueError::InvalidConversionRule.into()),
 		}
 	}
-}
+}*/
 
+/*
 // Non-SQL
 // - DateTime
 fn parse_error_into(error: ParseError) -> Error {
@@ -301,3 +330,4 @@ impl CastWithRules<NaiveDateTime> for Value {
 		}
 	}
 }
+*/
diff --git a/src/data/value/declare.rs b/src/data/value/declare.rs
new file mode 100644
index 00000000..b9619902
--- /dev/null
+++ b/src/data/value/declare.rs
@@ -0,0 +1,62 @@
+use {
+	super::methods::{BinaryOperations, UnaryOperations},
+	crate::{BigEndian, Cast, Error},
+	enum_dispatch::enum_dispatch,
+	serde::{Deserialize, Serialize},
+	std::cmp::{Ord, Ordering},
+	std::fmt::Debug,
+};
+
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, PartialOrd)]
+pub struct Null;
+
+//#[enum_dispatch(Value)]
+//pub trait Valued: BigEndian {}
+//impl<T: Valued> BigEndian for T {}
+
+macro_rules! value_types {
+	( $($representation:ident: $type:ty),* ) => {
+		#[enum_dispatch(Value)]
+		pub trait Valued: Into<Value> + BigEndian + BinaryOperations<Self> + UnaryOperations $(+ Cast<$type>)* {}
+
+		//#[enum_dispatch]
+		#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, PartialOrd)]
+		pub enum Value {
+			$($representation($type)),*
+		}
+	}
+}
+
+impl Value {
+	pub const NULL: Self = Self::Null(Null);
+}
+
+impl Eq for Value {}
+impl Ord for Value {
+	fn cmp(&self, other: &Value) -> Ordering {
+		self.partial_cmp(other).unwrap_or(Ordering::Equal)
+	}
+}
+
+impl Into<Value> for bool {
+	fn into(self) -> Value {
+		Value::Bool(self)
+	}
+}
+
+/*value_types!(
+	Boolean:	bool,
+	UInteger:	u64,
+	Integer:	i64,
+	Float:		f64,
+	Text:			String,
+);*/
+
+value_types!(
+	Bool: bool,
+	U64: u64,
+	I64: i64,
+	F64: f64,
+	Str: String,
+	Null: Null
+);
diff --git a/src/data/value/literal.rs b/src/data/value/literal.rs
index 6f150807..e98ba388 100644
--- a/src/data/value/literal.rs
+++ b/src/data/value/literal.rs
@@ -19,7 +19,7 @@ impl<'a> TryFrom<&'a AstValue> for Value {
 				)
 				.map_err(|_| ValueError::FailedToParseNumber.into()),
 			AstValue::SingleQuotedString(value) => Ok(Value::Str(value.clone())),
-			AstValue::Null => Ok(Value::Null),
+			AstValue::Null => Ok(Value::NULL),
 			_ => Err(ValueError::UnimplementedLiteralType.into()),
 		}
 	}
diff --git a/src/data/value/methods/aggregate.rs b/src/data/value/methods/aggregate.rs
index 5b866b4d..c3d976a2 100644
--- a/src/data/value/methods/aggregate.rs
+++ b/src/data/value/methods/aggregate.rs
@@ -14,9 +14,9 @@ use {
 impl Value {
 	pub fn aggregate_count(self, other: Value) -> Result<Value> {
 		Ok(Value::Internal(match (self, other) {
-			(Value::Null, Value::Null) => 0,
+			(Value::Null(_), Value::Null(_)) => 0,
 			(Value::Internal(self_val), Value::Internal(other_val)) => self_val + other_val,
-			(Value::Internal(val), Value::Null) | (Value::Null, Value::Internal(val)) => val,
+			(Value::Internal(val), Value::Null(_)) | (Value::Null(_), Value::Internal(val)) => val,
 			(Value::Internal(val), _) | (_, Value::Internal(val)) => val + 1,
 			(_, _) => 2,
 		}))
@@ -24,7 +24,7 @@ impl Value {
 	pub fn aggregate_min(self, other: Value) -> Result<Value> {
 		Ok(
 			if matches!(self.partial_cmp(&other), Some(Ordering::Less))
-				|| matches!(other, Value::Null)
+				|| matches!(other, Value::Null(_))
 			{
 				self
 			} else {
@@ -35,7 +35,7 @@ impl Value {
 	pub fn aggregate_max(self, other: Value) -> Result<Value> {
 		Ok(
 			if matches!(self.partial_cmp(&other), Some(Ordering::Greater))
-				|| matches!(other, Value::Null)
+				|| matches!(other, Value::Null(_))
 			{
 				self
 			} else {
diff --git a/src/data/value/methods/binary.rs b/src/data/value/methods/binary.rs
index 2d326793..c85745fb 100644
--- a/src/data/value/methods/binary.rs
+++ b/src/data/value/methods/binary.rs
@@ -1,130 +1,67 @@
-#![allow(clippy::should_implement_trait)] // TODO
-
 use {
-	super::ValueCore,
-	crate::{Convert, ConvertFrom, Result, Value, ValueError},
+	crate::{Cast, Result, Value, Valued},
+	std::ops::*,
 };
 
-// These were using references, they now consume their variables. See ::recipe.
-macro_rules! natural_binary_op {
-    ($name: ident, $trait: ident, $op: tt) => {
-        pub fn $name<Core>(self, other: Self) -> Result<Self>
-        where
-            Core: ValueCore + $trait<Output = Core>,
-        {
-            let (left, right) = (Core::convert_from(self)?, Core::convert_from(other)?);
-            let result = left $op right;
-            Ok(result.into())
-        }
-    };
-}
-macro_rules! natural_binary_ops {
-    ($(($name: ident, $trait: ident, $op: tt, $generic_name: ident)),+) => {
-        use std::ops::{$($trait),+};
-        impl Value {
-            $(
-                natural_binary_op!($name, $trait, $op);
-                generic!($name, $generic_name);
-            )+
-        }
-    }
+pub trait BinaryOperations<O: Valued>:
+	Sized + ValuedBinaryOperations<O> + BooleanBinaryOperations
+{
 }
 
-macro_rules! boolean_binary_op {
-    ($name: ident, $op: tt) => {
-        pub fn $name(self, other: Self) -> Result<Self>
-        {
-            let (left, right): (bool, bool) = (self.convert()?, other.convert()?);
-            let result = left $op right;
-            Ok(result.into())
-        }
-    };
-}
-macro_rules! boolean_binary_ops {
-    ($(($name: ident, $op: tt)),+) => {
-        impl Value {
-            $(boolean_binary_op!($name, $op);)+
-        }
-    }
+pub trait ValuedBinaryOperations<O: Valued>:
+	Sized
+	+ Add<Output = O>
+	+ Sub<Output = O>
+	+ Mul<Output = O>
+	+ Div<Output = O>
+	+ Rem<Output = O>
+	+ BitAnd<Output = O>
+	+ BitOr<Output = O>
+	+ BitXor<Output = O>
+{
 }
 
-macro_rules! comparative_binary_op {
-    ($name: ident, $op: tt) => {
-        pub fn $name(self, other: Self) -> Result<Self> {
-            Ok(Value::Bool(self $op other))
-        }
-    };
-}
-macro_rules! comparative_binary_ops {
-    ($(($name: ident, $op: tt)),+) => {
-        impl Value {
-            $(comparative_binary_op!($name, $op);)+
-        }
-    }
-}
+pub trait BooleanBinaryOperations: Sized + Eq + Ord {}
 
-macro_rules! generic {
-	($name: ident, $generic_name: ident) => {
-		pub fn $generic_name(self, other: Self) -> Result<Self> {
-			if matches!(self, Value::Null) || matches!(other, Value::Null) {
-				Ok(Value::Null)
-			} else if !i64::convert_from(self.clone()).is_err()
-				&& !i64::convert_from(other.clone()).is_err()
-			{
-				self.$name::<i64>(other)
-			} else if !f64::convert_from(self.clone()).is_err()
-				&& !f64::convert_from(other.clone()).is_err()
-			{
-				self.$name::<f64>(other)
-			} else {
-				Err(ValueError::OnlySupportsNumeric(
-					if f64::convert_from(self.clone()).is_err() {
-						self
-					} else {
-						other
-					},
-					stringify!($name),
-				)
-				.into())
-			}
-		}
-	};
+pub enum BinaryOperation {
+	Add,
+	Sub,
+	Mul,
+	Div,
+	Rem,
+	Eq,
+	Lt,
+	LtEq,
+	Gt,
+	GtEq,
+	And,
+	Or,
+	Xor,
 }
 
-natural_binary_ops!(
-	(add, Add, +, generic_add),
-	(subtract, Sub, -, generic_subtract),
-	(multiply, Mul, *, generic_multiply),
-	(divide, Div, /, generic_divide),
-	(modulus, Rem, %, generic_modulus)
-);
-
-boolean_binary_ops!(
-	(and, &),
-	(or, |),
-	(xor, ^)
-);
-
-comparative_binary_ops!(
-	(eq, ==),
-	(not_eq, !=),
-	(gt, >),
-	(gt_eq, >=),
-	(lt, <),
-	(lt_eq, <=)
-);
+impl BinaryOperation {
+	pub fn exec<I: BinaryOperations<O>, O: Valued>(&self, left: I, right: I) -> Result<Value> {
+		use BinaryOperation::*;
+		Ok(match self {
+			Add => left.add(right).into(),
+			Sub => left.sub(right).into(),
+			Mul => left.mul(right).into(),
+			Div => left.div(right).into(),
+			Rem => left.rem(right).into(),
+			Eq => (left == right).into(),
+			Lt => (left < right).into(),
+			LtEq => (left <= right).into(),
+			Gt => (left > right).into(),
+			GtEq => (left >= right).into(),
+			And => (left & right).into(),
+			Or => (left | right).into(),
+			Xor => (left ^ right).into(),
+		})
+	}
+}
 
-impl Value {
+/*impl Value {
 	pub fn string_concat(self, other: Self) -> Result<Self> {
-		if matches!(self, Value::Null) || matches!(other, Value::Null) {
-			Ok(Value::Null)
-		} else {
-			Ok(format!(
-				"{}{}",
-				String::convert_from(self)?,
-				String::convert_from(other)?
-			)
-			.into())
-		}
+		Ok(format!("{}{}", self.cast()?, other.cast()?).into())
 	}
-}
+}*/
diff --git a/src/data/value/methods/function.rs b/src/data/value/methods/function.rs
index d4fd6e2a..d6d0b896 100644
--- a/src/data/value/methods/function.rs
+++ b/src/data/value/methods/function.rs
@@ -146,6 +146,6 @@ impl Value {
 		})
 	}
 	pub fn function_try_convert(arguments: Vec<Self>) -> Result<Self> {
-		Ok(Value::function_convert(arguments).unwrap_or(Value::Null))
+		Ok(Value::function_convert(arguments).unwrap_or(Value::NULL))
 	}
 }
diff --git a/src/data/value/methods/mod.rs b/src/data/value/methods/mod.rs
index 97cfe033..310eee63 100644
--- a/src/data/value/methods/mod.rs
+++ b/src/data/value/methods/mod.rs
@@ -4,13 +4,13 @@ mod function;
 mod timestamp;
 mod unary;
 mod utility;
-use {
-	crate::{ConvertFrom, Value},
-	std::convert::Into,
+
+pub use {
+	binary::{BinaryOperation, BinaryOperations},
+	unary::{UnaryOperation, UnaryOperations},
 };
 
-pub trait ValueCore: Into<Value> + ConvertFrom<Value> {}
-impl ValueCore for bool {}
-impl ValueCore for i64 {}
-impl ValueCore for f64 {}
-impl ValueCore for String {}
+enum Operation {
+	UnaryOperation(UnaryOperation),
+	BinaryOperation(BinaryOperation),
+}
diff --git a/src/data/value/methods/timestamp.rs b/src/data/value/methods/timestamp.rs
index e10d6d29..b4cc58b0 100644
--- a/src/data/value/methods/timestamp.rs
+++ b/src/data/value/methods/timestamp.rs
@@ -13,7 +13,7 @@ use {
 macro_rules! protect_null {
 	($protect: expr) => {
 		match $protect {
-			Value::Null => return Ok(Value::Null),
+			Value::Null(_) => return Ok(Value::NULL),
 			other => other,
 		}
 	};
diff --git a/src/data/value/methods/unary.rs b/src/data/value/methods/unary.rs
index 05a9302b..8788dd91 100644
--- a/src/data/value/methods/unary.rs
+++ b/src/data/value/methods/unary.rs
@@ -1,52 +1,14 @@
 use {
-	super::ValueCore,
-	crate::{Convert, ConvertFrom, Result, Value, ValueError},
-	std::ops::Neg,
+	crate::{Result, Value},
+	enum_dispatch::enum_dispatch,
+	std::ops::*,
 };
 
-macro_rules! generic {
-	($name: ident, $generic_name: ident) => {
-		pub fn $generic_name(self) -> Result<Self> {
-			if !i64::convert_from(self.clone()).is_err() {
-				// TODO: Improve
-				self.$name::<i64>()
-			} else if !f64::convert_from(self.clone()).is_err() {
-				self.$name::<f64>()
-			} else {
-				Err(ValueError::OnlySupportsNumeric(self, stringify!($name)).into())
-			}
-		}
-	};
-}
+pub trait UnaryOperations: Not + Neg {}
 
-#[allow(clippy::should_implement_trait)] // TODO
+pub enum UnaryOperation {}
 impl Value {
-	pub fn unary_plus<Core>(self) -> Result<Self>
-	where
-		Core: ValueCore + Clone,
-	{
-		let core = Core::convert_from(self)?;
-		let result = core;
-		Ok(result.into())
-	}
-	pub fn unary_minus<Core>(self) -> Result<Self>
-	where
-		Core: ValueCore + Neg<Output = Core>,
-	{
-		let core = Core::convert_from(self)?;
-		let result = -core;
-		Ok(result.into())
-	}
-
-	generic!(unary_plus, generic_unary_plus);
-	generic!(unary_minus, generic_unary_minus);
-
-	pub fn not(self) -> Result<Self> {
-		let boolean: bool = self.convert()?;
-		let result = !boolean;
-		Ok(result.into())
-	}
 	pub fn is_null(self) -> Result<Self> {
-		Ok(Value::Bool(matches!(self, Value::Null)))
+		Ok(Value::Bool(matches!(self, Value::Null(_))))
 	}
 }
diff --git a/src/data/value/methods/utility.rs b/src/data/value/methods/utility.rs
index d104f798..84372b98 100644
--- a/src/data/value/methods/utility.rs
+++ b/src/data/value/methods/utility.rs
@@ -1,11 +1,11 @@
 use {
-	crate::{Convert, Result, Value, ValueError},
+	crate::{Cast, Convert, Result, Value, ValueError},
 	std::cmp::min,
 };
 
 macro_rules! protect_null {
 	($protect: expr) => {
-		if matches!($protect, Value::Null) {
+		if matches!($protect, Value::Null(_)) {
 			return Ok($protect);
 		}
 	};
@@ -13,14 +13,14 @@ macro_rules! protect_null {
 
 impl Value {
 	pub fn if_null(self, alternative: Self) -> Self {
-		if !matches!(self, Value::Null) {
+		if !matches!(self, Value::Null(_)) {
 			self
 		} else {
 			alternative
 		}
 	}
 	pub fn null_if(self, evaluate: Self) -> Result<Self> {
-		Ok(if self == evaluate { Value::Null } else { self })
+		Ok(if self == evaluate { Value::NULL } else { self })
 	}
 	pub fn iif(self, case_true: Self, case_false: Self) -> Result<Self> {
 		Ok(if self.convert()? {
@@ -32,18 +32,18 @@ impl Value {
 
 	pub fn to_uppercase(self) -> Result<Self> {
 		protect_null!(self);
-		let string: String = self.convert()?;
+		let string: String = self.cast()?;
 		Ok(string.to_uppercase().into())
 	}
 	pub fn to_lowercase(self) -> Result<Self> {
 		protect_null!(self);
-		let string: String = self.convert()?;
+		let string: String = self.cast()?;
 		Ok(string.to_lowercase().into())
 	}
 	pub fn left(self, length: Value) -> Result<Value> {
 		protect_null!(self);
 		protect_null!(length);
-		let length: i64 = length.convert()?;
+		let length: i64 = length.cast()?;
 		if length < 0 {
 			return Err(ValueError::BadInput(length.into()).into());
 		}
@@ -93,7 +93,7 @@ impl Value {
 	}
 
 	pub fn round(self, places: Value) -> Result<Value> {
-		if matches!(self, Value::Null) {
+		if matches!(self, Value::Null(_)) {
 			return Ok(self);
 		}
 		let value: f64 = self.convert()?;
diff --git a/src/data/value/mod.rs b/src/data/value/mod.rs
index 0e618a13..47d7b08a 100644
--- a/src/data/value/mod.rs
+++ b/src/data/value/mod.rs
@@ -1,17 +1,9 @@
-use {
-	crate::result::Result,
-	serde::{Deserialize, Serialize},
-	sqlparser::ast::DataType,
-	std::{
-		cmp::Ordering,
-		fmt::Debug,
-		hash::{Hash, Hasher},
-	},
-};
+use {crate::result::Result, sqlparser::ast::DataType, std::cmp::Ordering};
 
 mod big_endian;
 mod cast;
 mod convert;
+mod declare;
 mod error;
 mod literal;
 mod methods;
@@ -22,6 +14,7 @@ pub use {
 	big_endian::BigEndian,
 	cast::{Cast, CastWithRules},
 	convert::{Convert, ConvertFrom},
+	declare::{Null, Value, Valued},
 	error::ValueError,
 	value_type::ValueType,
 };
@@ -65,127 +58,12 @@ pub use {
 ///
 /// Floats and Integers implicitly compare and convert.
 /// (Feature: `implicit_float_conversion`)
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub enum Value {
-	Null,
-
-	Bool(bool),
-	U64(u64),
-	I64(i64),
-	F64(f64),
-	Str(String),
 
-	Bytes(Vec<u8>),
-	Timestamp(i64),
-
-	Internal(i64),
-}
-
-impl Hash for Value {
+/*impl Hash for Value {
 	fn hash<H: Hasher>(&self, state: &mut H) {
 		self.to_be_bytes().hash(state)
 	}
-}
-impl Eq for Value {}
-impl Ord for Value {
-	fn cmp(&self, other: &Self) -> Ordering {
-		self.partial_cmp(other).unwrap_or(Ordering::Equal)
-	}
-}
-
-impl From<bool> for Value {
-	fn from(from: bool) -> Value {
-		Value::Bool(from)
-	}
-}
-impl From<i64> for Value {
-	fn from(from: i64) -> Value {
-		Value::I64(from)
-	}
-}
-impl From<i32> for Value {
-	fn from(from: i32) -> Value {
-		Value::I64(from as i64)
-	}
-}
-impl From<u64> for Value {
-	fn from(from: u64) -> Value {
-		Value::U64(from)
-	}
-}
-impl From<u32> for Value {
-	fn from(from: u32) -> Value {
-		Value::U64(from as u64)
-	}
-}
-impl From<f64> for Value {
-	fn from(from: f64) -> Value {
-		Value::F64(from)
-	}
-}
-impl From<String> for Value {
-	fn from(from: String) -> Value {
-		Value::Str(from)
-	}
-}
-
-impl<T: Into<Value>> From<Option<T>> for Value {
-	fn from(from: Option<T>) -> Value {
-		from.map(|v| v.into()).unwrap_or(Value::Null)
-	}
-}
-
-impl From<Value> for String {
-	// assumes all can be cast to string
-	fn from(from: Value) -> String {
-		from.cast().unwrap()
-	}
-}
-
-impl PartialEq for Value {
-	fn eq(&self, other: &Value) -> bool {
-		match (self, other) {
-			(Value::Bool(l), Value::Bool(r)) => l == r,
-			(Value::U64(l), Value::U64(r)) => l == r,
-			(Value::I64(l), Value::I64(r)) => l == r,
-			(Value::F64(l), Value::F64(r)) => l == r,
-			(Value::Str(l), Value::Str(r)) => l == r,
-			(Value::Bytes(l), Value::Bytes(r)) => l == r,
-			(Value::Timestamp(l), Value::Timestamp(r)) => l == r,
-
-			(Value::Internal(l), Value::Internal(r)) => l == r,
-
-			#[cfg(feature = "implicit_float_conversion")]
-			(Value::I64(l), Value::F64(r)) => (*l as f64) == *r,
-			#[cfg(feature = "implicit_float_conversion")]
-			(Value::F64(l), Value::I64(r)) => *l == (*r as f64),
-			_ => false,
-		}
-	}
-}
-
-impl PartialOrd for Value {
-	fn partial_cmp(&self, other: &Value) -> Option<Ordering> {
-		match (self, other) {
-			(Value::Bool(l), Value::Bool(r)) => Some(l.cmp(r)),
-			(Value::I64(l), Value::I64(r)) => Some(l.cmp(r)),
-			(Value::F64(l), Value::F64(r)) => l.partial_cmp(r),
-			(Value::Str(l), Value::Str(r)) => Some(l.cmp(r)),
-			(Value::Bytes(l), Value::Bytes(r)) => Some(l.cmp(r)),
-			(Value::Timestamp(l), Value::Timestamp(r)) => Some(l.cmp(r)),
-
-			(Value::Internal(l), Value::Internal(r)) => Some(l.cmp(r)),
-
-			#[cfg(feature = "implicit_float_conversion")]
-			(Value::I64(l), Value::F64(r)) => (*l as f64).partial_cmp(r),
-
-			#[cfg(feature = "implicit_float_conversion")]
-			(Value::F64(l), Value::I64(r)) => l.partial_cmp(&(*r as f64)),
-
-			_ => None,
-		}
-	}
-}
+}*/
 
 pub trait NullOrd {
 	fn null_cmp(&self, other: &Self) -> Option<Ordering>;
@@ -194,9 +72,9 @@ pub trait NullOrd {
 impl NullOrd for Value {
 	fn null_cmp(&self, other: &Self) -> Option<Ordering> {
 		self.partial_cmp(other).or(match (self, other) {
-			(Value::Null, Value::Null) => None,
-			(Value::Null, _) => Some(Ordering::Less),
-			(_, Value::Null) => Some(Ordering::Greater),
+			(Value::Null(_), Value::Null(_)) => None,
+			(Value::Null(_), _) => Some(Ordering::Less),
+			(_, Value::Null(_)) => Some(Ordering::Greater),
 			_ => None,
 		})
 	}
@@ -229,24 +107,16 @@ impl Value {
 
 		Ok(self)
 	}
-	pub fn is(&mut self, data_type: &ValueType) -> Result<()> {
+	/*pub fn is(&mut self, data_type: &ValueType) -> Result<()> {
 		match (data_type, &self) {
 			(ValueType::Bool, Value::Bool(_))
 			| (ValueType::U64, Value::U64(_))
 			| (ValueType::I64, Value::I64(_))
 			| (ValueType::F64, Value::F64(_))
 			| (ValueType::Str, Value::Str(_))
-			| (ValueType::Timestamp, Value::Timestamp(_))
+			//| (ValueType::Timestamp, Value::Timestamp(_))
 			| (ValueType::Any, _)
-			| (_, Value::Null) => Ok(()),
-			(ValueType::Timestamp, Value::I64(val)) => {
-				*self = Value::Timestamp(*val);
-				Ok(())
-			}
-			(ValueType::I64, Value::Timestamp(val)) => {
-				*self = Value::I64(*val);
-				Ok(())
-			}
+			| (_, Value::Null(_)) => Ok(()),
 			(ValueType::F64, Value::I64(_)) => {
 				*self = Value::F64(self.clone().cast()?);
 				Ok(())
@@ -257,7 +127,7 @@ impl Value {
 			}
 			.into()),
 		}
-	}
+	}*/
 
 	fn type_is_valid(&self, data_type: &DataType) -> bool {
 		matches!(
@@ -266,15 +136,15 @@ impl Value {
 				| (DataType::Int(_), Value::I64(_))
 				| (DataType::Float(_), Value::F64(_))
 				| (DataType::Text, Value::Str(_))
-				| (DataType::Boolean, Value::Null)
-				| (DataType::Int(_), Value::Null)
-				| (DataType::Float(_), Value::Null)
-				| (DataType::Text, Value::Null)
+				| (DataType::Boolean, Value::Null(_))
+				| (DataType::Int(_), Value::Null(_))
+				| (DataType::Float(_), Value::Null(_))
+				| (DataType::Text, Value::Null(_))
 		)
 	}
 
 	pub fn validate_null(&self, nullable: bool) -> Result<()> {
-		if !nullable && matches!(self, Value::Null) {
+		if !nullable && matches!(self, Value::Null(_)) {
 			return Err(ValueError::NullValueOnNotNullField.into());
 		}
 
diff --git a/src/data/value/serde_convert.rs b/src/data/value/serde_convert.rs
index 20a174c3..fee6fbb5 100644
--- a/src/data/value/serde_convert.rs
+++ b/src/data/value/serde_convert.rs
@@ -8,7 +8,7 @@ impl From<Value> for serde_json::value::Value {
 			Value::I64(value) => value.into(),
 			Value::F64(value) => value.into(),
 			Value::Str(value) => value.into(),
-			Value::Null => serde_json::value::Value::Null,
+			Value::Null(_) => serde_json::value::Value::Null,
 			other => {
 				let string: String = other.cast().unwrap();
 				string.into()
diff --git a/src/data/value/value_type/cast.rs b/src/data/value/value_type/cast.rs
index c2100482..f5210848 100644
--- a/src/data/value/value_type/cast.rs
+++ b/src/data/value/value_type/cast.rs
@@ -12,7 +12,7 @@ impl Value {
 			| (ValueType::F64, Value::F64(_))
 			| (ValueType::Str, Value::Str(_))
 			| (ValueType::Any, _) => Ok(self.clone()),
-			(_, Value::Null) => Ok(Value::Null),
+			(_, Value::Null(Null)) => Ok(Value::NULL),
 
 			(ValueType::Bool, value) => value.clone().cast().map(Value::Bool),
 			(ValueType::I64, value) => value.clone().cast().map(Value::I64),
diff --git a/src/databases/sheet/base.rs b/src/databases/sheet/base.rs
index c4e06282..4995dac3 100644
--- a/src/databases/sheet/base.rs
+++ b/src/databases/sheet/base.rs
@@ -58,7 +58,7 @@ impl DBBase for SheetDatabase {
 									.unwrap_or_default(),
 							)
 							.cast_valuetype(data_type)
-							.unwrap_or(Value::Null)
+							.unwrap_or(Value::NULL)
 						})
 						.collect()),
 				)
@@ -76,7 +76,7 @@ impl TryFrom<Cell> for Value {
 			"s" => Value::Str(cell.get_value().to_string()),
 			"b" => Value::Bool(Value::Str(cell.get_value().to_string()).cast()?),
 			"n" => Value::F64(Value::Str(cell.get_value().to_string()).cast()?),
-			"" => Value::Null,
+			"" => Value::NULL,
 			_ => return Err(DatabaseError::Unimplemented.into()),
 		})
 	}
diff --git a/src/databases/sled/mutable.rs b/src/databases/sled/mutable.rs
index 37ec8a06..8b741991 100644
--- a/src/databases/sled/mutable.rs
+++ b/src/databases/sled/mutable.rs
@@ -199,7 +199,7 @@ impl SledDatabase {
 	pub fn add_column(&mut self, table_name: &str, column: Column) -> Result<()> {
 		let value = match (&column.default, &column.is_nullable) {
 			(Some(_expr), _) => Err(DatabaseError::Unimplemented), // TODO
-			(None, true) => Ok(Value::Null),
+			(None, true) => Ok(Value::NULL),
 			(None, false) => Err(DatabaseError::Unimplemented),
 		}?;
 
diff --git a/src/executor/alter_row/auto_increment.rs b/src/executor/alter_row/auto_increment.rs
index 4078525f..225a484a 100644
--- a/src/executor/alter_row/auto_increment.rs
+++ b/src/executor/alter_row/auto_increment.rs
@@ -1,5 +1,5 @@
 #![cfg(feature = "auto-increment")]
-use crate::{Column, Glue, Result, Row, Value, ValueDefault};
+use crate::{Column, Glue, Null, Result, Row, Value, ValueDefault};
 
 impl Glue {
 	pub async fn auto_increment(
@@ -18,7 +18,7 @@ impl Glue {
 					index,
 					column.name.clone(),
 					rows.iter()
-						.filter(|row| matches!(row.0.get(index), Some(Value::Null)))
+						.filter(|row| matches!(row.0.get(index), Some(Value::Null(Null))))
 						.count() as i64,
 				)
 			})
@@ -33,7 +33,7 @@ impl Glue {
 		for row in rows.iter_mut() {
 			for ((index, _name), value) in &mut column_values {
 				let cell = row.0.get_mut(*index).unwrap();
-				if matches!(cell, Value::Null) {
+				if matches!(cell, Value::Null(Null)) {
 					*cell = Value::I64(*value);
 					*value += 1;
 				}
diff --git a/src/executor/query/mod.rs b/src/executor/query/mod.rs
index 7d6d139e..3d3b7024 100644
--- a/src/executor/query/mod.rs
+++ b/src/executor/query/mod.rs
@@ -108,7 +108,7 @@ impl Glue {
 				rows = rows
 					.into_iter()
 					.map(|mut row| {
-						row.resize(row_width, Value::Null);
+						row.resize(row_width, Value::NULL);
 						row
 					})
 					.collect();
diff --git a/src/executor/query/select/join/method.rs b/src/executor/query/select/join/method.rs
index 49d4e8f4..089b72a9 100644
--- a/src/executor/query/select/join/method.rs
+++ b/src/executor/query/select/join/method.rs
@@ -77,7 +77,7 @@ impl JoinMethod {
 						Ok(if inner_rows.is_empty() && join.includes_left() {
 							(
 								vec![],
-								vec![join_parts(left_row, vec![Value::Null; right_width])],
+								vec![join_parts(left_row, vec![Value::NULL; right_width])],
 							)
 						} else {
 							inner_rows.into_iter().unzip()
@@ -100,7 +100,7 @@ impl JoinMethod {
 					if !used_right_indexes.iter().any(|used| used == &index)
 						&& join.includes_right()
 					{
-						rows.push(join_parts(vec![Value::Null; left_width], row.clone()))
+						rows.push(join_parts(vec![Value::NULL; left_width], row.clone()))
 					}
 				});
 				rows
@@ -222,7 +222,7 @@ impl JoinMethod {
 					.map(|(_, left_rows)| {
 						left_rows
 							.into_iter()
-							.map(|left| join_parts(left, vec![Value::Null; right_width]))
+							.map(|left| join_parts(left, vec![Value::NULL; right_width]))
 							.collect::<Vec<Row>>()
 					})
 					.reduce(Vec::new, |mut all, set| {
@@ -258,7 +258,7 @@ impl JoinMethod {
 					.map(|(_, right_rows)| {
 						right_rows
 							.into_iter()
-							.map(|right| join_parts(vec![Value::Null; left_width], right))
+							.map(|right| join_parts(vec![Value::NULL; left_width], right))
 							.collect::<Vec<Row>>()
 					})
 					.reduce(Vec::new, |mut all, set| {
diff --git a/src/executor/query/select/order.rs b/src/executor/query/select/order.rs
index fd665a9e..2b7d827c 100644
--- a/src/executor/query/select/order.rs
+++ b/src/executor/query/select/order.rs
@@ -83,8 +83,8 @@ struct OrderTerm {
 impl OrderTerm {
 	pub fn sort(&self, order_item_a: &Value, order_item_b: &Value) -> Option<Ordering> {
 		let order = match (order_item_a, order_item_b) {
-			(Value::Null, Value::Null) => Ordering::Equal,
-			(Value::Null, _) | (_, Value::Null) => {
+			(Value::NULL, Value::NULL) => Ordering::Equal,
+			(Value::NULL, _) | (_, Value::NULL) => {
 				if self.prefer_nulls {
 					Ordering::Greater
 				} else {
diff --git a/src/glue/mod.rs b/src/glue/mod.rs
index da837c84..bcc43f74 100644
--- a/src/glue/mod.rs
+++ b/src/glue/mod.rs
@@ -212,7 +212,7 @@ impl Glue {
 				row.into_iter()
 					.map(|cell| {
 						Expr::Value(match cell {
-							Value::Null => AstValue::Null,
+							Value::NULL => AstValue::Null,
 							Value::Bool(value) => AstValue::Boolean(value),
 							Value::I64(value) => AstValue::Number(value.to_string(), false),
 							Value::F64(value) => AstValue::Number(value.to_string(), false),
diff --git a/tests/ability/base/aggregate/general.rs b/tests/ability/base/aggregate/general.rs
index 6e82dedb..b9270039 100644
--- a/tests/ability/base/aggregate/general.rs
+++ b/tests/ability/base/aggregate/general.rs
@@ -45,7 +45,7 @@ fn test(mut glue: multisql::Glue) {
 	{
 		let _expect = multisql::Payload::Select {
 			labels: vec![String::from("agg")],
-			rows: vec![multisql::Row(vec![multisql::Value::Null])],
+			rows: vec![multisql::Row(vec![multisql::Value::NULL])],
 		};
 		assert!(matches!(
 			glue.execute(
diff --git a/tests/util/mod.rs b/tests/util/mod.rs
index 37cbfb66..066608b0 100644
--- a/tests/util/mod.rs
+++ b/tests/util/mod.rs
@@ -129,7 +129,7 @@ macro_rules! select {
 	($($label: tt = $type: ident),* : _) => ({ // Crappy but working way of testing single NULL
 		multisql::Payload::Select {
 			labels: vec![$( stringify!($label).to_owned().replace("\"", "")),+],
-			rows: vec![multisql::Row(vec![multisql::Value::Null])]
+			rows: vec![multisql::Row(vec![multisql::Value::NULL])]
 		}
 	});
 }
