Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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