Skip to content

Commit

Permalink
all: Add new scalar type Int8
Browse files Browse the repository at this point in the history
  • Loading branch information
dotansimha committed Jun 4, 2023
1 parent 3d6645e commit 59e4719
Show file tree
Hide file tree
Showing 32 changed files with 442 additions and 19 deletions.
12 changes: 6 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions graph/src/data/store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ pub type Attribute = String;
pub const BYTES_SCALAR: &str = "Bytes";
pub const BIG_INT_SCALAR: &str = "BigInt";
pub const BIG_DECIMAL_SCALAR: &str = "BigDecimal";
pub const INT8_SCALAR: &str = "Int8";

#[derive(Clone, Debug, PartialEq)]
pub enum ValueType {
Expand All @@ -146,6 +147,7 @@ pub enum ValueType {
Bytes,
BigDecimal,
Int,
Int8,
String,
}

Expand All @@ -159,6 +161,7 @@ impl FromStr for ValueType {
"Bytes" => Ok(ValueType::Bytes),
"BigDecimal" => Ok(ValueType::BigDecimal),
"Int" => Ok(ValueType::Int),
"Int8" => Ok(ValueType::Int8),
"String" | "ID" => Ok(ValueType::String),
s => Err(anyhow!("Type not available in this context: {}", s)),
}
Expand Down Expand Up @@ -187,6 +190,7 @@ pub enum IdType {
pub enum Value {
String(String),
Int(i32),
Int8(i64),
BigDecimal(scalar::BigDecimal),
Bool(bool),
List(Vec<Value>),
Expand Down Expand Up @@ -224,6 +228,9 @@ impl stable_hash_legacy::StableHash for Value {
Int(inner) => {
stable_hash_legacy::StableHash::stable_hash(inner, sequence_number, state)
}
Int8(inner) => {
stable_hash_legacy::StableHash::stable_hash(inner, sequence_number, state)
}
BigDecimal(inner) => {
stable_hash_legacy::StableHash::stable_hash(inner, sequence_number, state)
}
Expand Down Expand Up @@ -282,6 +289,10 @@ impl StableHash for Value {
inner.stable_hash(field_address.child(0), state);
7
}
Int8(inner) => {
inner.stable_hash(field_address.child(0), state);
8
}
};

state.write(field_address, &[variant])
Expand Down Expand Up @@ -325,6 +336,9 @@ impl Value {
QueryExecutionError::ValueParseError("BigInt".to_string(), format!("{}", e))
})?),
BIG_DECIMAL_SCALAR => Value::BigDecimal(scalar::BigDecimal::from_str(s)?),
INT8_SCALAR => Value::Int8(s.parse::<i64>().map_err(|_| {
QueryExecutionError::ValueParseError("Int8".to_string(), format!("{}", s))
})?),
_ => Value::String(s.clone()),
}
}
Expand Down Expand Up @@ -416,6 +430,7 @@ impl Value {
Value::Bool(_) => "Boolean".to_owned(),
Value::Bytes(_) => "Bytes".to_owned(),
Value::Int(_) => "Int".to_owned(),
Value::Int8(_) => "Int8".to_owned(),
Value::List(values) => {
if let Some(v) = values.first() {
format!("[{}]", v.type_name())
Expand All @@ -436,6 +451,7 @@ impl Value {
| (Value::Bool(_), ValueType::Boolean)
| (Value::Bytes(_), ValueType::Bytes)
| (Value::Int(_), ValueType::Int)
| (Value::Int8(_), ValueType::Int8)
| (Value::Null, _) => true,
(Value::List(values), _) if is_list => values
.iter()
Expand All @@ -457,6 +473,7 @@ impl fmt::Display for Value {
match self {
Value::String(s) => s.to_string(),
Value::Int(i) => i.to_string(),
Value::Int8(i) => i.to_string(),
Value::BigDecimal(d) => d.to_string(),
Value::Bool(b) => b.to_string(),
Value::Null => "null".to_string(),
Expand All @@ -474,6 +491,7 @@ impl fmt::Debug for Value {
match self {
Self::String(s) => f.debug_tuple("String").field(s).finish(),
Self::Int(i) => f.debug_tuple("Int").field(i).finish(),
Self::Int8(i) => f.debug_tuple("Int8").field(i).finish(),
Self::BigDecimal(d) => d.fmt(f),
Self::Bool(arg0) => f.debug_tuple("Bool").field(arg0).finish(),
Self::List(arg0) => f.debug_tuple("List").field(arg0).finish(),
Expand All @@ -489,6 +507,7 @@ impl From<Value> for q::Value {
match value {
Value::String(s) => q::Value::String(s),
Value::Int(i) => q::Value::Int(q::Number::from(i)),
Value::Int8(i) => q::Value::String(i.to_string()),
Value::BigDecimal(d) => q::Value::String(d.to_string()),
Value::Bool(b) => q::Value::Boolean(b),
Value::Null => q::Value::Null,
Expand All @@ -506,6 +525,7 @@ impl From<Value> for r::Value {
match value {
Value::String(s) => r::Value::String(s),
Value::Int(i) => r::Value::Int(i as i64),
Value::Int8(i) => r::Value::String(i.to_string()),
Value::BigDecimal(d) => r::Value::String(d.to_string()),
Value::Bool(b) => r::Value::Boolean(b),
Value::Null => r::Value::Null,
Expand Down Expand Up @@ -572,6 +592,12 @@ impl From<u64> for Value {
}
}

impl From<i64> for Value {
fn from(value: i64) -> Value {
Value::Int8(value.into())
}
}

impl TryFrom<Value> for Option<scalar::BigInt> {
type Error = Error;

Expand Down
15 changes: 14 additions & 1 deletion graph/src/data/store/sql.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::anyhow;
use diesel::pg::Pg;
use diesel::serialize::{self, Output, ToSql};
use diesel::sql_types::{Binary, Bool, Integer, Text};
use diesel::sql_types::{Binary, Bool, Int8, Integer, Text};

use std::io::Write;
use std::str::FromStr;
Expand Down Expand Up @@ -34,6 +34,19 @@ impl ToSql<Integer, Pg> for Value {
}
}

impl ToSql<Int8, Pg> for Value {
fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
match self {
Value::Int8(i) => <i64 as ToSql<Int8, Pg>>::to_sql(i, out),
v => Err(anyhow!(
"Failed to convert non-int8 attribute value to int8 in SQL: {}",
v
)
.into()),
}
}
}

impl ToSql<Text, Pg> for Value {
fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
match self {
Expand Down
2 changes: 2 additions & 0 deletions graph/src/data/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,8 @@ impl Value {
Err(Value::Int(num))
}
}
("Int8", Value::Int(num)) => Ok(Value::String(num.to_string())),
("Int8", Value::String(num)) => Ok(Value::String(num)),
("String", Value::String(s)) => Ok(Value::String(s)),
("ID", Value::String(s)) => Ok(Value::String(s)),
("ID", Value::Int(n)) => Ok(Value::String(n.to_string())),
Expand Down
1 change: 1 addition & 0 deletions graph/src/runtime/gas/size_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ impl GasSizeOf for Value {
Value::Null => Gas(1),
Value::List(list) => list.gas_size_of(),
Value::Int(int) => int.gas_size_of(),
Value::Int8(int) => int.gas_size_of(),
Value::Bytes(bytes) => bytes.gas_size_of(),
Value::Bool(bool) => bool.gas_size_of(),
Value::BigInt(big_int) => big_int.gas_size_of(),
Expand Down
4 changes: 4 additions & 0 deletions graph/src/schema/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,7 @@ fn field_scalar_filter_input_values(
"BigDecimal" => vec!["", "not", "gt", "lt", "gte", "lte", "in", "not_in"],
"ID" => vec!["", "not", "gt", "lt", "gte", "lte", "in", "not_in"],
"Int" => vec!["", "not", "gt", "lt", "gte", "lte", "in", "not_in"],
"Int8" => vec!["", "not", "gt", "lt", "gte", "lte", "in", "not_in"],
"String" => vec![
"",
"not",
Expand Down Expand Up @@ -1114,6 +1115,9 @@ mod tests {
schema
.get_named_type("String")
.expect("String type is missing in API schema");
schema
.get_named_type("Int8")
.expect("Int8 type is missing in API schema");
}

#[test]
Expand Down
4 changes: 4 additions & 0 deletions graph/src/schema/meta.graphql
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# GraphQL core functionality
scalar Boolean
scalar ID
""" 4 bytes signed integer """
scalar Int
scalar Float
scalar String
Expand All @@ -19,9 +20,12 @@ directive @subgraphId(id: String!) on OBJECT
"creates a virtual field on the entity that may be queried but cannot be set manually through the mappings API."
directive @derivedFrom(field: String!) on FIELD_DEFINITION

# Additional scalar types
scalar BigDecimal
scalar Bytes
scalar BigInt
""" 8 bytes signed integer """
scalar Int8

# The type names are purposely awkward to minimize the risk of them
# colliding with user-supplied types
Expand Down
2 changes: 1 addition & 1 deletion graph/src/util/cache_weight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ impl CacheWeight for Value {
Value::List(values) => values.indirect_weight(),
Value::Bytes(bytes) => bytes.indirect_weight(),
Value::BigInt(n) => n.indirect_weight(),
Value::Int(_) | Value::Bool(_) | Value::Null => 0,
Value::Int8(_) | Value::Int(_) | Value::Bool(_) | Value::Null => 0,
}
}
}
Expand Down
19 changes: 19 additions & 0 deletions graphql/src/values/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ impl MaybeCoercible<ScalarType> for q::Value {
Err(q::Value::Int(num))
}
}
("Int8", q::Value::Int(num)) => {
let n = num.as_i64().ok_or_else(|| q::Value::Int(num.clone()))?;
Ok(r::Value::Int(n))
}
("String", q::Value::String(s)) => Ok(r::Value::String(s)),
("ID", q::Value::String(s)) => Ok(r::Value::String(s)),
("ID", q::Value::Int(n)) => Ok(r::Value::String(
Expand Down Expand Up @@ -395,6 +399,21 @@ mod tests {
);
}

#[test]
fn coerce_int8_scalar() {
let int8_type = TypeDefinition::Scalar(ScalarType::new("Int8".to_string()));
let resolver = |_: &str| Some(&int8_type);

assert_eq!(
coerce_to_definition(Value::Int(1234.into()), "", &resolver),
Ok(Value::String("1234".to_string()))
);
assert_eq!(
coerce_to_definition(Value::Int((-1234_i32).into()), "", &resolver,),
Ok(Value::String("-1234".to_string()))
);
}

#[test]
fn coerce_bytes_scalar() {
let bytes_type = TypeDefinition::Scalar(ScalarType::new("Bytes".to_string()));
Expand Down
6 changes: 6 additions & 0 deletions runtime/test/src/test/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,12 @@ async fn test_abi_store_value(api_version: Version) {
let new_value: Value = module.asc_get(new_value_ptr).unwrap();
assert_eq!(new_value, Value::Int(int));

// Value::Int8
let int8 = i64::min_value();
let new_value_ptr = module.takes_val_returns_ptr("value_from_int8", int8);
let new_value: Value = module.asc_get(new_value_ptr).unwrap();
assert_eq!(new_value, Value::Int8(int8));

// Value::BigDecimal
let big_decimal = BigDecimal::from_str("3.14159001").unwrap();
let new_value_ptr = module.invoke_export1("value_from_big_decimal", &big_decimal);
Expand Down
8 changes: 8 additions & 0 deletions runtime/test/wasm_test/api_version_0_0_4/abi_store_value.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ enum ValueKind {
NULL = 5,
BYTES = 6,
BIG_INT = 7,
INT8 = 8,
}

// Big enough to fit any pointer or native `this.data`.
Expand Down Expand Up @@ -43,6 +44,13 @@ export function value_from_int(int: i32): Value {
return value
}

export function value_from_int8(int: i64): Value {
let value = new Value();
value.kind = ValueKind.INT8;
value.data = int as i64
return value
}

export function value_from_big_decimal(float: BigInt): Value {
let value = new Value();
value.kind = ValueKind.BIG_DECIMAL;
Expand Down
Binary file modified runtime/test/wasm_test/api_version_0_0_4/abi_store_value.wasm
Binary file not shown.
8 changes: 8 additions & 0 deletions runtime/test/wasm_test/api_version_0_0_5/abi_store_value.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ export function value_from_int(int: i32): Value {
return value
}

export function value_from_int8(int: i64): Value {
let value = new Value();
value.kind = ValueKind.INT8;
value.data = int as i64
return value
}


export function value_from_big_decimal(float: BigInt): Value {
let value = new Value();
value.kind = ValueKind.BIG_DECIMAL;
Expand Down
Binary file modified runtime/test/wasm_test/api_version_0_0_5/abi_store_value.wasm
Binary file not shown.
1 change: 1 addition & 0 deletions runtime/test/wasm_test/api_version_0_0_5/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export enum ValueKind {
NULL = 5,
BYTES = 6,
BIG_INT = 7,
INT8 = 8
}
// Big enough to fit any pointer or native `this.data`.
export type Payload = u64
Expand Down
8 changes: 8 additions & 0 deletions runtime/wasm/src/asc_abi/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,12 @@ impl From<EnumPayload> for f64 {
}
}

impl From<EnumPayload> for i64 {
fn from(payload: EnumPayload) -> i64 {
payload.0 as i64
}
}

impl From<EnumPayload> for bool {
fn from(payload: EnumPayload) -> bool {
payload.0 != 0
Expand Down Expand Up @@ -546,6 +552,7 @@ pub enum StoreValueKind {
Null,
Bytes,
BigInt,
Int8,
}

impl StoreValueKind {
Expand All @@ -555,6 +562,7 @@ impl StoreValueKind {
match value {
Value::String(_) => StoreValueKind::String,
Value::Int(_) => StoreValueKind::Int,
Value::Int8(_) => StoreValueKind::Int8,
Value::BigDecimal(_) => StoreValueKind::BigDecimal,
Value::Bool(_) => StoreValueKind::Bool,
Value::List(_) => StoreValueKind::Array,
Expand Down
2 changes: 2 additions & 0 deletions runtime/wasm/src/to_from/external.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ impl FromAscObj<AscEnum<StoreValueKind>> for store::Value {
Value::String(asc_get(heap, ptr, gas, depth)?)
}
StoreValueKind::Int => Value::Int(i32::from(payload)),
StoreValueKind::Int8 => Value::Int8(i64::from(payload)),
StoreValueKind::BigDecimal => {
let ptr: AscPtr<AscBigDecimal> = AscPtr::from(payload);
Value::BigDecimal(asc_get(heap, ptr, gas, depth)?)
Expand Down Expand Up @@ -292,6 +293,7 @@ impl ToAscObj<AscEnum<StoreValueKind>> for store::Value {
let payload = match self {
Value::String(string) => asc_new(heap, string.as_str(), gas)?.into(),
Value::Int(n) => EnumPayload::from(*n),
Value::Int8(n) => EnumPayload::from(*n),
Value::BigDecimal(n) => asc_new(heap, n, gas)?.into(),
Value::Bool(b) => EnumPayload::from(*b),
Value::List(array) => asc_new(heap, array.as_slice(), gas)?.into(),
Expand Down
Loading

0 comments on commit 59e4719

Please sign in to comment.